/*!
 * Gitee-Frontend.js v0.22.0
 * (c) 2021 Gitee
 * Released under the MIT License.
 */
(function () {
	'use strict';

	function unwrapExports (x) {
		return x && x.__esModule && Object.prototype.hasOwnProperty.call(x, 'default') ? x['default'] : x;
	}

	function createCommonjsModule(fn, module) {
		return module = { exports: {} }, fn(module, module.exports), module.exports;
	}

	var _typeof_1 = createCommonjsModule(function (module) {
	  function _typeof(obj) {
	    "@babel/helpers - typeof";

	    if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") {
	      module.exports = _typeof = function _typeof(obj) {
	        return typeof obj;
	      };

	      module.exports["default"] = module.exports, module.exports.__esModule = true;
	    } else {
	      module.exports = _typeof = function _typeof(obj) {
	        return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj;
	      };

	      module.exports["default"] = module.exports, module.exports.__esModule = true;
	    }

	    return _typeof(obj);
	  }

	  module.exports = _typeof;
	  module.exports["default"] = module.exports, module.exports.__esModule = true;
	});

	var _typeof = unwrapExports(_typeof_1);

	var classCallCheck = createCommonjsModule(function (module) {
	  function _classCallCheck(instance, Constructor) {
	    if (!(instance instanceof Constructor)) {
	      throw new TypeError("Cannot call a class as a function");
	    }
	  }

	  module.exports = _classCallCheck;
	  module.exports["default"] = module.exports, module.exports.__esModule = true;
	});
	var _classCallCheck = unwrapExports(classCallCheck);

	var createClass = createCommonjsModule(function (module) {
	  function _defineProperties(target, props) {
	    for (var i = 0; i < props.length; i++) {
	      var descriptor = props[i];
	      descriptor.enumerable = descriptor.enumerable || false;
	      descriptor.configurable = true;
	      if ("value" in descriptor) descriptor.writable = true;
	      Object.defineProperty(target, descriptor.key, descriptor);
	    }
	  }

	  function _createClass(Constructor, protoProps, staticProps) {
	    if (protoProps) _defineProperties(Constructor.prototype, protoProps);
	    if (staticProps) _defineProperties(Constructor, staticProps);
	    return Constructor;
	  }

	  module.exports = _createClass;
	  module.exports["default"] = module.exports, module.exports.__esModule = true;
	});
	var _createClass = unwrapExports(createClass);

	var assertThisInitialized = createCommonjsModule(function (module) {
	  function _assertThisInitialized(self) {
	    if (self === void 0) {
	      throw new ReferenceError("this hasn't been initialised - super() hasn't been called");
	    }

	    return self;
	  }

	  module.exports = _assertThisInitialized;
	  module.exports["default"] = module.exports, module.exports.__esModule = true;
	});
	var _assertThisInitialized = unwrapExports(assertThisInitialized);

	var possibleConstructorReturn = createCommonjsModule(function (module) {
	  var _typeof = _typeof_1["default"];

	  function _possibleConstructorReturn(self, call) {
	    if (call && (_typeof(call) === "object" || typeof call === "function")) {
	      return call;
	    }

	    return assertThisInitialized(self);
	  }

	  module.exports = _possibleConstructorReturn;
	  module.exports["default"] = module.exports, module.exports.__esModule = true;
	});
	var _possibleConstructorReturn = unwrapExports(possibleConstructorReturn);

	var getPrototypeOf = createCommonjsModule(function (module) {
	  function _getPrototypeOf(o) {
	    module.exports = _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf : function _getPrototypeOf(o) {
	      return o.__proto__ || Object.getPrototypeOf(o);
	    };
	    module.exports["default"] = module.exports, module.exports.__esModule = true;
	    return _getPrototypeOf(o);
	  }

	  module.exports = _getPrototypeOf;
	  module.exports["default"] = module.exports, module.exports.__esModule = true;
	});
	var _getPrototypeOf = unwrapExports(getPrototypeOf);

	var setPrototypeOf = createCommonjsModule(function (module) {
	  function _setPrototypeOf(o, p) {
	    module.exports = _setPrototypeOf = Object.setPrototypeOf || function _setPrototypeOf(o, p) {
	      o.__proto__ = p;
	      return o;
	    };

	    module.exports["default"] = module.exports, module.exports.__esModule = true;
	    return _setPrototypeOf(o, p);
	  }

	  module.exports = _setPrototypeOf;
	  module.exports["default"] = module.exports, module.exports.__esModule = true;
	});
	unwrapExports(setPrototypeOf);

	var inherits = createCommonjsModule(function (module) {
	  function _inherits(subClass, superClass) {
	    if (typeof superClass !== "function" && superClass !== null) {
	      throw new TypeError("Super expression must either be null or a function");
	    }

	    subClass.prototype = Object.create(superClass && superClass.prototype, {
	      constructor: {
	        value: subClass,
	        writable: true,
	        configurable: true
	      }
	    });
	    if (superClass) setPrototypeOf(subClass, superClass);
	  }

	  module.exports = _inherits;
	  module.exports["default"] = module.exports, module.exports.__esModule = true;
	});
	var _inherits = unwrapExports(inherits);

	/* eslint-disable no-console */
	var defaults = {
	  filters: [],
	  groups: [],
	  text: {
	    loading: 'loading...',
	    placeholder: 'Search or filter results...',
	    searchHelp: 'Press Enter or click to search',
	    selectOtherFilter: 'Select other filter',
	    history: 'Histroy',
	    clearHistory: 'Clear history'
	  },
	  removeIconClass: 'icon times',
	  history: {
	    limit: 5,
	    store: window.localStorage,
	    storeKey: 'GiteeSearchHistory'
	  },
	  data: function data() {
	    return {};
	  },
	  callback: function callback(data) {
	    console.log(data);
	  }
	};
	function Config(config) {
	  $.extend(this, defaults, config);

	  if (config.text) {
	    $.extend(this.text, config.text);
	  }
	}

	/* eslint-disable indent */
	var template = {
	  container: ['<div class="filtered-search-box-input-container">', '<ul class="tokens-container">', '<li class="input-token ui search dropdown">', '<input autocomplete="off" class="search filtered-search">', '<div class="menu filter-items"></div>', '</li>', '</ul>', '</div>'].join(''),
	  btnClearSearch: ['<button class="clear-search" type="button">', '<i aria-hidden="true" data-hidden="true" class="{iconClass}"></i>', '</button>'].join(''),
	  itemIcon: '<i class="item-icon{class}" style="{style}"></i>',
	  itemDivider: '<div class="divider"></div>',
	  itemImage: '<img class="item-image ui avatar image" alt="image" src="{content}" />',
	  itemDescription: '<span class="description">{content}</span>',
	  inputDropdownItem: ['<div class="item{class}" data-value="{key}">', '{icon}{name}{placeholder}', '</div>'].join(''),
	  filterDropdownItem: ['<div class="item{class}" data-value="{value}" data-tab="{key}">', '{icon}{image}{name}<span class="item-keywords">{keywords}</span>{description}', '</div>'].join(''),
	  filterDropdownTabs: "\n    <div class=\"header tabs-wrapper\">\n  ",
	  filterDropdownTab: "\n    <span class=\"tab {active}\" data-tab=\"{key}\">{name}</span>\n  ",
	  filterSearchTip: "\n    <div class=\"item search-tips\" data-tab=\"visitor\">{searchTip}</div>\n  ",
	  inputDropdownHeader: '<div class="header">{header}</div>',
	  visualTokenValue: ['<div class="value-container{class}" style="{style}">', '<div class="value" data-value="{value}">{icon}{image}{name}</div>', '<div class="remove-token inverted" role="button">', '<i class="{iconClass}"></i>', '</div>', '</div>'].join(''),
	  visualSearchTerm: ['<li class="js-visual-token filtered-search-term">', '<div class="name">{value}</div>', '</li>'].join(''),
	  visualToken: ['<li class="js-visual-token filtered-search-token" data-key="{key}">', '<div class="selectable" role="button">', '<div class="name">{name}</div>', '{value}', '</div>', '</li>'].join('')
	};

	var htmlEscape = function () {
	  var $el = $('<div/>');
	  return function (text) {
	    return $el.text(text).html();
	  };
	}();
	function cleanCopy(obj) {
	  return JSON.parse(JSON.stringify(obj));
	}
	function isEmptyFilterToken($token) {
	  return $token.find('.value').length < 1;
	}
	function isSearchTermToken($token) {
	  return $token.hasClass('filtered-search-term');
	}
	function findListItem(list, cmp) {
	  var target = null;
	  list.some(function (item) {
	    if (cmp(item)) {
	      target = item;
	      return true;
	    }

	    return false;
	  });
	  return target;
	}
	function findFilterItemByValue(filter, value) {
	  var valueStr = value.toString();
	  return findListItem(filter.items, function (item) {
	    return item.value.toString() === valueStr;
	  });
	}
	function findFilterItemByName(filter, name) {
	  if (!filter.items) {
	    return null;
	  }

	  return findListItem(filter.items, function (item) {
	    return item.name === name;
	  });
	}

	function render(tmpl, data) {
	  var html = tmpl;
	  Object.keys(data).forEach(function (k) {
	    html = html.replace('{' + k + '}', data[k]);
	  });
	  return html;
	}

	var itemDivider = template.itemDivider;
	function renderFilterDropdownTabs(tabs) {
	  var html = $(template.filterDropdownTabs);
	  tabs.forEach(function (item) {
	    return html.append(render(template.filterDropdownTab, item));
	  });
	  return html;
	}
	function renderSearchTip(searchTip) {
	  var html = render(template.filterSearchTip, {
	    searchTip: searchTip
	  });
	  return html;
	}
	function renderFilterDropdownItem(item) {
	  var html = template.filterDropdownItem;
	  var keymap = {
	    image: 'itemImage',
	    description: 'itemDescription'
	  };
	  Object.keys(keymap).forEach(function (k) {
	    var node = '';

	    if (item[k]) {
	      node = template[keymap[k]].replace('{content}', item[k]);
	    }

	    html = html.replace('{' + k + '}', node);
	  });

	  if (item.icon) {
	    html = render(html, {
	      icon: render(template.itemIcon, {
	        "class": ' ' + item.icon,
	        style: item.iconStyle || ''
	      })
	    });
	  } else {
	    html = render(html, {
	      icon: ''
	    });
	  }

	  return render(html, {
	    name: htmlEscape(item.name),
	    value: item.value,
	    keywords: htmlEscape(item.keywords || ''),
	    "class": item["class"] ? ' ' + item["class"] : '',
	    key: item.key || ''
	  });
	}
	function renderInputDropdownItem(item) {
	  var data = {};
	  data.key = item.key || 'cmd';
	  data.name = item.name;

	  if (item.icon) {
	    data.icon = '<i class="' + item.icon + '"></i>';
	  } else {
	    data.icon = '';
	  }

	  if (item.placeholder) {
	    data.placeholder = ':' + item.placeholder;
	  } else {
	    data.placeholder = '';
	  }

	  if (item["class"]) {
	    data["class"] = ' ' + item["class"];
	  } else {
	    data["class"] = '';
	  }

	  return render(template.inputDropdownItem, data);
	}
	function renderItemIcon(data) {
	  if (data.icon) {
	    return render(template.itemIcon, {
	      style: data.iconStyle || '',
	      "class": ' ' + data.icon
	    });
	  }

	  return '';
	}
	function renderInputDropdownHeader(header) {
	  return render(template.inputDropdownHeader, {
	    header: header
	  });
	}
	function renderVisualSearchTerm(data) {
	  return render(template.visualSearchTerm, {
	    value: htmlEscape(data.value)
	  });
	}
	var Renderer =
	/*#__PURE__*/
	function () {
	  function Renderer() {
	    _classCallCheck(this, Renderer);
	  }

	  _createClass(Renderer, [{
	    key: "renderFilterTokenValueByItem",
	    value: function renderFilterTokenValueByItem(item) {
	      var html = template.visualTokenValue;
	      html = render(html, {
	        name: htmlEscape(item.name),
	        value: item.value,
	        iconClass: this.config.removeIconClass
	      });
	      html = render(html, {
	        icon: renderItemIcon(item)
	      });

	      if (item.image) {
	        html = render(html, {
	          image: render(template.itemImage, {
	            content: item.image
	          })
	        });
	      } else {
	        html = render(html, {
	          image: ''
	        });
	      }

	      if (item.color) {
	        return render(html, {
	          "class": ' has-color',
	          style: 'background-color: ' + item.color
	        });
	      }

	      return render(html, {
	        "class": '',
	        style: ''
	      });
	    }
	  }, {
	    key: "renderFilterTokenValue",
	    value: function renderFilterTokenValue(filter, value) {
	      var i;
	      var item;
	      var items = filter.items;
	      var valueStr = value.toString();

	      if (filter.type === 'daterange') {
	        return this.renderFilterTokenValueByItem({
	          name: value,
	          value: value
	        });
	      }

	      if (_typeof(filter.none) === 'object') {
	        items = [filter.none].concat(items);
	      }

	      for (i = 0; i < items.length; ++i) {
	        item = items[i];

	        if (item.value.toString() === valueStr) {
	          return this.renderFilterTokenValueByItem(item);
	        }
	      }

	      return '';
	    }
	  }, {
	    key: "renderVisualToken",
	    value: function renderVisualToken(filter, value) {
	      var _this = this;

	      var values;
	      var valuesHtml = '';
	      var html = template.visualToken;

	      if (filter.multiple) {
	        values = value;
	      } else {
	        values = [value];
	      }

	      html = render(template.visualToken, filter);

	      if (typeof value !== 'undefined') {
	        values.forEach(function (val) {
	          valuesHtml += _this.renderFilterTokenValue(filter, val);
	        });
	      }

	      html = html.replace('{value}', valuesHtml);
	      return html;
	    }
	  }, {
	    key: "renderBody",
	    value: function renderBody() {
	      return [template.container, render(template.btnClearSearch, {
	        iconClass: this.config.removeIconClass
	      })].join('');
	    }
	  }]);

	  return Renderer;
	}();

	/* eslint-disable no-param-reassign */

	function onIntent(e) {
	  var i;
	  var item;
	  var that = e.data["this"];
	  var $target = $(e.target);
	  var classes = ['.filtered-search-box'];
	  that.logger.log('onIntent()'); // 如果点击的是组件内的元素，则保持激活状态

	  for (i = 0; i < classes.length; ++i) {
	    if ($target.parents(classes[i]).length > 0) {
	      that.lockShow();
	      that.focus();
	      return;
	    }
	  }

	  if (!that.target) {
	    return;
	  }

	  that.active = false; // 如果输入框后面没有筛选器，就不移动输入框了

	  if (that.$inputDropdown.next('.js-visual-token').length < 1) {
	    return;
	  }

	  item = findFilterItemByName(that.target, that.targetValue);

	  if (item) {
	    that.selectFilterValue(item.value);
	  }

	  that.$input.val('');
	  that.clearTargetFilter();
	  that.resetInputPosition();
	} // 初始化筛选器的事件处理


	function initTokenEventHandler(that) {
	  that.$el.on('click', '.js-visual-token', function (e) {
	    var $value;
	    var $target = $(e.target);
	    var $token = $target.parents('.js-visual-token');
	    e.stopPropagation(); // 如果点击的是删除按钮

	    if ($target.hasClass('remove-token') || $target.parent().hasClass('remove-token')) {
	      $value = $target.parents('.value-container').find('.value');
	      that.removeFilterValue($token, $value.data('value')); // 如果当前输入框已经获得焦点，则让它保持焦点

	      if (that.hasFocus()) {
	        that.focus();
	        that.deferFocusTime();
	      }

	      return;
	    }

	    that.editToken($token);
	  });
	} // 初始化输入框内的输入事件捕获，用于处理用户手动输入的筛选条件


	function initInputTokenCatch(that) {
	  var keyHandlers = {
	    'Backspace': function Backspace(value) {
	      var $token; // 只在输入框内容为空时处理条件删除操作

	      if (value) {
	        return;
	      }

	      if (that.target) {
	        $token = that.$target; // 如果该筛选标记元素没有值，则切换编辑筛选器名称

	        if (isEmptyFilterToken($token)) {
	          value = that.target.name;
	          that.clearTargetFilter();
	          that.removeFilterToken($token);
	        } else {
	          that.popCurrentFilterValue();
	          that.buildInputDropdown();
	        }

	        return;
	      } // 取上一个筛选器，然后删除它的最后一个选项


	      $token = that.$inputDropdown.prev('.js-visual-token');

	      if ($token.length > 0) {
	        if (isSearchTermToken($token)) {
	          that.editTerm();
	          return;
	        }

	        that.popFilterValue($token);

	        if (isEmptyFilterToken($token)) {
	          $token.remove();
	        }

	        that.buildInputDropdown();
	      }
	    },
	    'Enter': function Enter() {
	      if (!that.target) {
	        that.submit();
	        that.buildInputDropdown();
	        setTimeout(function () {
	          that.$input.focus();
	        }, 10);
	      }
	    },
	    ':': function _(value) {
	      var filter;

	      if (that.target) {
	        that.$input.val(value);
	        return;
	      }

	      filter = that.getFilterByName(value);

	      if (filter && that.newFilter(filter.key)) {
	        that.$input.val('');
	        return;
	      }

	      that.$input.val(value);
	    },
	    // 筛选选项分割符，针对可多选的筛选器
	    ',': function _(value) {
	      var item;

	      if (!that.target) {
	        return;
	      }

	      item = findFilterItemByName(that.target, value);

	      if (item && that.selectFilterValue(item.value)) {
	        that.$input.val('');
	        that.input = '';
	        that.buildFilterDropdown(that.target);
	      } else {
	        that.$input.val(value);
	      }
	    },
	    // 筛选结束符
	    ';': function _(value) {
	      var item;

	      if (!that.target) {
	        that.$input.val(value);
	        return;
	      }

	      item = findFilterItemByName(that.target, value);

	      if (item && that.selectFilterValue(item.value)) {
	        that.$input.val('');
	        that.input = '';
	        that.clearTargetFilter();
	      } else {
	        that.$input.val(value);
	      }
	    }
	  };
	  that.$input.on({
	    focus: function focus() {
	      that.$el.addClass('focus');
	    },
	    blur: function blur() {
	      that.$el.removeClass('focus');
	      /**
	      that.active = false
	      that.deferFocusTime() */
	    },
	    input: function input() {
	      that.input = that.$input.val();
	      that.updateState();

	      if (that.target && that.target.searchOption) {
	        var key = that.target.key;

	        if (that.target.timeOutId) {
	          clearTimeout(that.target.timeOutId);
	        }

	        that.target.timeOutId = setTimeout(function () {
	          if (that.input.length) {
	            if (!that.target || !that.target.searchOption) return;
	            that.target.searchOption.fetcher(that.input, function (data) {
	              if (key === that.target.key) {
	                that.target.items = that.target.items.filter(function (item) {
	                  return item.key !== that.target.searchOption.key;
	                });
	                var items = that.target.searchOption.converter(data);
	                that.target.items = that.target.items.concat(items);
	                that.buildRemoteSearchDropdownItems(that.target.searchOption.key, items);
	              }

	              that.setTabSelected();
	            });
	          } else {
	            that.buildRemoteSearchDropdownItems(that.target.searchOption.key, []);

	            if (that.$inputDropdownMenu.find('.item').not('.filtered').length) {
	              that.buildSearchTip(that.target.searchOption.searchTip);
	            }

	            that.$el.find(".tab[data-tab=".concat(that.target.tabs[0].key, "]")).trigger('click');
	          }
	        }, 400);
	      }
	    }
	  });
	  that.$el.on('click', function () {
	    that.focus();
	  });
	  that.$input.on('keydown', function (e) {
	    var val = that.$input.val();

	    if (!keyHandlers[e.key]) {
	      return;
	    } // 延迟一会，避免在给输入框赋值后又被后面的 inout 事件重置


	    setTimeout(function () {
	      keyHandlers[e.key](val);
	    }, 10);
	  });
	}

	function initTabEventHandler(target) {
	  target.$el.on('click', '.tab', function (e) {
	    target.$inputDropdownMenu.find('.tab').removeClass('active');
	    $(e.target).addClass('active');
	    target.$inputDropdownMenu.find('.item').addClass('hide');
	    target.$inputDropdownMenu.find(".item[data-tab=".concat($(e.target).data('tab'), "]")).removeClass('hide');
	  });
	} // 初始化“清除”按钮


	function initClearButton(that) {
	  that.$btnClearSearch.on('click', function () {
	    that.clear();
	    that.commit();
	  });
	}

	function bindIntent(target) {
	  $(document).on('mousedown', {
	    "this": target
	  }, onIntent);
	}
	function unbindIntent() {
	  $(document).off('mousedown', onIntent);
	} // 阻止已冒泡到 document 的 click 事件的处理

	function stopIntent(that) {
	  unbindIntent();
	  setTimeout(function () {
	    bindIntent(that);
	  }, 100);
	}
	function bindEventHandlers(target) {
	  initTokenEventHandler(target);
	  initInputTokenCatch(target);
	  initClearButton(target);
	  initTabEventHandler(target);
	}
	function unbindEventHandlers() {
	  unbindIntent();
	}

	var Builder =
	/*#__PURE__*/
	function (_Renderer) {
	  _inherits(Builder, _Renderer);

	  function Builder() {
	    _classCallCheck(this, Builder);

	    return _possibleConstructorReturn(this, _getPrototypeOf(Builder).apply(this, arguments));
	  }

	  _createClass(Builder, [{
	    key: "buildFilterDropdownItems",

	    /**
	     * 构建筛选器的下拉菜单选项
	     * @param {Object} filter 筛选器对象
	     */
	    value: function buildFilterDropdownItems(filter) {
	      var that = this;
	      var item = {};
	      that.$inputDropdownMenu.empty(); // 如果条件支持多选，则添加一条选项，让用户点击退出此条件的选择

	      if (filter.multiple) {
	        that.$inputDropdownMenu.append(renderInputDropdownItem({
	          key: '<cmd:back>',
	          icon: 'icon angle double left',
	          "class": 'item-fixed',
	          name: that.text.selectOtherFilter
	        }), itemDivider);
	      } // 如果有设置“无“选项


	      if (_typeof(filter.none) === 'object') {
	        Object.keys(filter.none).forEach(function (k) {
	          item[k] = filter.none[k];
	        });

	        if (item["class"]) {
	          item["class"] = "".concat(item["class"], " item-fixed");
	        } else {
	          item["class"] = 'item-fixed';
	        }

	        that.$inputDropdownMenu.append(renderFilterDropdownItem(item), itemDivider);
	      }

	      if (filter.tabs && filter.tabs.length) {
	        that.$inputDropdownMenu.append(renderFilterDropdownTabs(filter.tabs));
	      }

	      this.getFilterAvailableItems(filter).forEach(function (filterItem) {
	        that.$inputDropdownMenu.append(renderFilterDropdownItem(filterItem));
	      });

	      if (filter.searchOption) {
	        that.$inputDropdownMenu.append(renderSearchTip(filter.searchOption.searchTip));
	      }

	      if (filter.tabs && filter.tabs.length) {
	        that.$el.find(".tab[data-tab=".concat(filter.tabs[0].key, "]")).addClass('active');
	        that.$inputDropdownMenu.find('.item').addClass('hide');
	        that.$inputDropdownMenu.find(".item[data-tab=".concat(filter.tabs[0].key, "]")).removeClass('hide');
	      }

	      that.$inputDropdown.dropdown('refresh').dropdown('search'); // .dropdown('search') 防止远程结果为空时下拉框显示有问题
	    }
	  }, {
	    key: "buildRemoteSearchDropdownItems",
	    value: function buildRemoteSearchDropdownItems(key, items) {
	      var _this = this;

	      this.$inputDropdownMenu.find(".item[data-tab=".concat(key, "]")).remove();
	      items.forEach(function (filterItem) {
	        _this.$inputDropdownMenu.append(renderFilterDropdownItem(filterItem));
	      });
	    }
	  }, {
	    key: "buildSearchTip",
	    value: function buildSearchTip(searchTip) {
	      this.$inputDropdownMenu.append(renderSearchTip(searchTip));
	    }
	  }, {
	    key: "buildFilterDropdownRemoteTabItems",
	    value: function buildFilterDropdownRemoteTabItems(filter) {
	      var that = this;
	      that.$inputDropdownMenu.empty().append(renderInputDropdownItem({
	        key: '<cmd:wait>',
	        icon: 'ui active inline mini loader',
	        "class": 'item-fixed',
	        name: that.text.loading,
	        type: filter.type
	      }));
	      that.loadFilterRemoteItems(filter, function () {
	        if (that.target && that.target.key === filter.key) {
	          that.buildFilterDropdownItems(filter);
	        }
	      });
	    }
	  }, {
	    key: "buildFilterDropdownRemoteItems",
	    value: function buildFilterDropdownRemoteItems(filter) {
	      var that = this;
	      that.$inputDropdownMenu.empty().append(renderInputDropdownItem({
	        key: '<cmd:wait>',
	        icon: 'ui active inline mini loader',
	        "class": 'item-fixed',
	        name: that.text.loading,
	        type: filter.type
	      }));
	      that.loadFilterRemoteItems(filter, function () {
	        if (that.target && that.target.key === filter.key) {
	          that.buildFilterDropdownItems(filter);
	        }
	      });
	    }
	    /**
	     * 构建时间范围选择器
	     * @param {Object} filter 筛选器对象
	     */

	  }, {
	    key: "buildDateRangePicker",
	    value: function buildDateRangePicker(filter) {
	      var picker;
	      var that = this;
	      var value = this.targetValue;
	      var values;
	      that.$inputDropdown.dropdown({
	        on: 'custom',
	        onShow: function onShow() {
	          return false;
	        }
	      }).dropdown('hide');
	      that.removeDateRangePicker();
	      that.$input.daterangepicker(filter.config);
	      picker = that.$input.data('daterangepicker');

	      if (value) {
	        values = value.split(picker.locale.separator);
	        picker.setStartDate(values[0]);
	        picker.setEndDate(values[1]);
	      }

	      that.$input.on({
	        'apply.daterangepicker': function applyDaterangepicker() {
	          var start = picker.startDate.format(picker.locale.format);
	          var end = picker.endDate.format(picker.locale.format);
	          that.selectFilterValue(start + picker.locale.separator + end);
	          that.clearTargetFilter();
	          that.$input.val('');
	          picker.remove();
	        },
	        'cancel.daterangepicker': function cancelDaterangepicker() {
	          that.selectFilterValue(value);
	          that.clearTargetFilter();
	          that.$input.val('');
	          picker.remove();
	        }
	      });
	      picker.show();
	    }
	    /**
	     * 构建筛选器的下拉框，列出当前筛选器的可选选项
	     * @param {Object} filter 筛选器对象
	     */

	  }, {
	    key: "buildFilterDropdown",
	    value: function buildFilterDropdown(filter) {
	      var that = this;
	      that.updatePlaceholder();

	      if (filter.type === 'daterange') {
	        this.buildDateRangePicker(filter);
	        return;
	      }

	      if (filter.tabs && filter.tabs.length) {
	        this.$tokens.find('.menu.transition.visible').addClass('with-tabs');
	        that.buildFilterDropdownRemoteTabItems(filter);
	      } else {
	        this.$tokens.find('.menu.transition.visible').removeClass('with-tabs');

	        if (_typeof(filter.remote) === 'object') {
	          that.buildFilterDropdownRemoteItems(filter);
	        } else {
	          that.buildFilterDropdownItems(filter);
	        }
	      }

	      that.$inputDropdown.removeClass('input-filter-token').addClass('input-filter-value-token').dropdown({
	        forceSelection: false,
	        fullTextSearch: true,
	        selectOnKeydown: false,
	        onHide: function onHide() {
	          that.logger.log('buildFilterDropdown() hide?', !that.hasFocus()); // 根据当前状态确定是否阻止隐藏下拉框

	          return that.onHide();
	        },
	        action: function action(_text, value) {
	          var item;
	          that.lockShow();

	          if (!value) {
	            return true;
	          }

	          if (that.execCommand(value)) {
	            return true;
	          }

	          that.input = '';
	          that.targetValue = '';

	          if (_typeof(filter.none) === 'object' && filter.none.value.toString() === value) {
	            that.clearFilterValue();
	            that.selectFilterValue(value);
	            that.clearTargetFilter();
	            return false;
	          }

	          item = that.getCurrentFilterItem(value);

	          if (item) {
	            that.selectFilterValue(value);
	          } // 如果是多选，则重置下拉框


	          if (filter.multiple) {
	            // 没有可选选项就退出编辑筛选器
	            if (!that.visibleFilter(filter)) {
	              that.clearTargetFilter();
	            } else {
	              that.buildFilterDropdown(filter);
	              that.$input.val('');
	              that.$input.focus();

	              if (filter.tabs) {
	                that.setTabSelected();
	              }
	            }
	          } else {
	            that.clearTargetFilter();
	          }

	          stopIntent(that);
	          return false;
	        },
	        onChange: function onChange(value) {
	          var item;
	          that.lockShow();

	          if (value && value.indexOf('<cmd:') === 0) {
	            return;
	          }

	          item = that.getCurrentFilterItem(value);

	          if (item) {
	            that.$input.val(item.name);
	          }
	        }
	      }).dropdown('clear');
	      this.logger.log('[' + filter.key + ']', 'buildFilterDropdown()');
	    }
	    /**
	     * 构建已分组的下拉菜单选项
	     * @param {Array} 分组参数列表
	     * @returns {Array} 已被分组的筛选器的 key 列表
	     */

	  }, {
	    key: "buildGroupedDropdownItems",
	    value: function buildGroupedDropdownItems(groups) {
	      var that = this;
	      var groupedFilters = [];
	      groups.forEach(function (group) {
	        var html = '';
	        that.filters.forEach(function (filter) {
	          if (group.keys.indexOf(filter.key) < 0) {
	            return;
	          }

	          groupedFilters.push(filter.key);

	          if (!that.visibleFilter(filter)) {
	            return;
	          }

	          html += renderInputDropdownItem(filter);
	        });

	        if (html) {
	          html = renderInputDropdownHeader(group.name) + html;
	        }

	        that.$inputDropdownMenu.append(html);
	      });
	      return groupedFilters;
	    }
	  }, {
	    key: "buildHistoryItems",
	    value: function buildHistoryItems() {
	      if (this.config.history && this.history.load().length > 0) {
	        this.$inputDropdownMenu.append(renderInputDropdownHeader(this.text.history), this.history.render(), renderInputDropdownItem({
	          key: '<cmd:clear-history>',
	          name: this.text.clearHistory
	        }), itemDivider);
	      }
	    }
	  }, {
	    key: "clearSearchItem",
	    value: function clearSearchItem() {
	      this.$input.off('input.dropdown');
	    } // 构建“搜索”选项

	  }, {
	    key: "buildSearchItem",
	    value: function buildSearchItem() {
	      var that = this;
	      var $cmd = $(renderInputDropdownItem({
	        key: '<cmd:search>',
	        icon: 'icon search',
	        "class": 'item-fixed',
	        name: that.text.searchHelp
	      }));
	      that.$inputDropdownMenu.append($cmd); // 在输入内容时，更新“搜索”选项的值，让下拉框能将它作为第一个匹配的选项，并默认选中它

	      that.$input.on('input.dropdown', function () {
	        // 将输入框当前值放在前面，确保下拉框能够搜索匹配到
	        $cmd.attr('data-value', that.$input.val() + ';<cmd:search>');
	        that.$inputDropdown.dropdown('refresh');
	      });
	    }
	  }, {
	    key: "buildInputDropdown",
	    value: function buildInputDropdown() {
	      var html = '';
	      var that = this;
	      var groupedFilters = [];
	      this.clearSearchItem();

	      if (that.target) {
	        that.buildFilterDropdown(that.target);
	        return;
	      }

	      that.updatePlaceholder();
	      that.logger.log('buildInputDropdown()');
	      that.$inputDropdownMenu.empty();
	      that.buildSearchItem();
	      that.buildHistoryItems();

	      if (that.groups.length > 0) {
	        groupedFilters = that.buildGroupedDropdownItems(that.groups);
	      }

	      that.filters.forEach(function (filter) {
	        if (groupedFilters.indexOf(filter.key) >= 0) {
	          return;
	        }

	        if (!that.visibleFilter(filter)) {
	          return;
	        }

	        html += renderInputDropdownItem(filter);
	      });

	      if (html && groupedFilters.length > 0) {
	        html = itemDivider + html;
	      }

	      that.$inputDropdownMenu.append(html);
	      that.$inputDropdown.addClass('input-filter-token').removeClass('input-filter-value-token').dropdown({
	        forceSelection: false,
	        selectOnKeydown: false,
	        onHide: function onHide() {
	          if (that.input) {
	            that.applyInput();
	          }

	          if (!that.hasFocus()) {
	            that.resetInputPosition();
	          }

	          that.logger.log('buildInputDropdown() hide?', !that.hasFocus());
	          return that.onHide();
	        },
	        action: function action(_text, value) {
	          that.logger.log('action():', value);
	          that.lockShow();

	          if (value) {
	            if (that.newFilter(value)) {
	              return;
	            }
	          }

	          if (that.input) {
	            that.applyInput();
	            that.buildInputDropdown();
	            that.execCommand(value);
	          } else if (that.execCommand(value)) {
	            // 清空下拉框的值，以取消选项的“已选中”的效果
	            that.$inputDropdown.dropdown('clear');
	            that.logger.log('execCommand');
	            that.applyInput();
	          }
	        }
	      }).dropdown('clear');
	    } // 构建已选中的筛选器标记

	  }, {
	    key: "buildFilterTokens",
	    value: function buildFilterTokens() {
	      var that = this;
	      that.loadingFilters = 0;
	      that.filters.forEach(function (filter) {
	        var html;
	        var value = that.data[filter.key];
	        that.logger.log('buildFilterTokens():', filter.key);

	        if (typeof value === 'undefined') {
	          return;
	        }

	        if (filter.multiple) {
	          if (value.length < 1) {
	            return;
	          }
	        } else if (value === '') {
	          return;
	        }

	        if (that.checkFilterItemsLoaded(filter)) {
	          html = that.renderVisualToken(filter, value);
	          $(html).insertBefore(that.$inputDropdown);
	          return;
	        }

	        that.setDisabled(true);
	        that.loadingFilters += 1;
	        that.loadFilterRemoteItems(filter, function () {
	          var selector = '.js-visual-token[data-key="' + filter.key + '"]';
	          that.$el.find(selector).remove();
	          html = that.renderVisualToken(filter, that.data[filter.key]);
	          $(html).insertBefore(that.$inputDropdown);
	          that.loadingFilters -= 1;

	          if (that.loadingFilters < 1) {
	            that.setDisabled(false);
	            that.buildSearchTerm();
	          }
	        });
	      });
	    } // 更新搜索条件的内容及位置

	  }, {
	    key: "buildSearchTerm",
	    value: function buildSearchTerm() {
	      if (this.$search && this.$search.length > 0) {
	        if (this.data.search) {
	          this.$search.find('.name').text(this.data.search);
	        } else {
	          this.$search.remove();
	          this.$search = null;
	          return;
	        }
	      } else if (this.data.search) {
	        this.$search = $(renderVisualSearchTerm({
	          value: this.data.search
	        }));
	      } else {
	        return;
	      } // 移动元素时会触发下拉框的 hide 行为，而 onHide() 回调里有调用 applyInput() 方法，
	      // 等于递归调用了一次，为避免重复记录搜索词，在这里加个延迟


	      setTimeout(function () {
	        // 顺带更新条件和输入框的位置
	        this.deferFocusTime();
	        this.$tokens.append(this.$search, this.$inputDropdown);
	      }.bind(this));
	    } // 构建组件基础内容和功能

	  }, {
	    key: "build",
	    value: function build() {
	      this.$el.html(this.renderBody());
	      this.$el.addClass('filtered-search-box');
	      this.$tokens = this.$el.find('.tokens-container');
	      this.$input = this.$el.find('.filtered-search');
	      this.$inputDropdown = this.$input.parent();
	      this.$inputDropdownMenu = this.$inputDropdown.find('.filter-items');
	      this.$btnClearSearch = this.$el.find('.clear-search');
	      this.buildInputDropdown();
	      this.buildFilterTokens();
	      this.buildSearchTerm();
	      bindIntent(this);
	      this.updateClearButton();
	    }
	  }]);

	  return Builder;
	}(Renderer);

	function renderHistroyItem(item) {
	  return renderInputDropdownItem({
	    name: item.name,
	    "class": 'history-item',
	    key: '<cmd:apply:' + escape(JSON.stringify(item.value)) + '>'
	  });
	}

	var History =
	/*#__PURE__*/
	function () {
	  function History(config) {
	    _classCallCheck(this, History);

	    if (_typeof(config) === 'object') {
	      $.extend(this, defaults.history, config);
	    } else {
	      $.extend(this, defaults.history);
	    }
	  }

	  _createClass(History, [{
	    key: "load",
	    value: function load() {
	      try {
	        var data = JSON.parse(this.store.getItem(this.storeKey));

	        if (data instanceof Array) {
	          return data;
	        }
	      } catch (e) {
	        return [];
	      }

	      return [];
	    }
	  }, {
	    key: "generateItem",
	    value: function generateItem(filters, data) {
	      var name = []; // 生成条件组名称

	      filters.forEach(function (filter) {
	        var value = data[filter.key];

	        if (!value) {
	          return;
	        }

	        if (filter.none && value.toString() === filter.none.value.toString()) {
	          name.push(filter.name + ': ' + filter.none.name);
	          return;
	        }

	        if (filter.multiple && value instanceof Array) {
	          var values = [];
	          value.forEach(function (v) {
	            var item = findFilterItemByValue(filter, v);

	            if (item) {
	              values.push(item.name);
	            }
	          });

	          if (values.length > 0) {
	            name.push(filter.name + ': ' + values.join(', '));
	          }

	          return;
	        }

	        if (filter.type === 'daterange') {
	          name.push(filter.name + ': ' + value);
	          return;
	        }

	        var item = findFilterItemByValue(filter, value);

	        if (item) {
	          name.push(filter.name + ': ' + item.name);
	        }
	      });

	      if (data.search) {
	        name.push(data.search);
	      }

	      if (name.length < 1) {
	        return false;
	      }

	      name = name.join('; ');
	      return {
	        name: name,
	        value: data
	      };
	    }
	    /**
	     * 添加历史记录
	     * @param {Array} filters 筛选器列表，用于为条件组生成名称
	     */

	  }, {
	    key: "add",
	    value: function add(filters, data) {
	      var history = this.load();
	      var item = this.generateItem(filters, data); // 删除同名的历史记录

	      for (var i = 0; i < history.length; ++i) {
	        if (history[i].name === item.name) {
	          history.splice(i, 1);
	          break;
	        }
	      }

	      history.splice(0, 0, item);
	      history = history.splice(0, this.limit);
	      this.store.setItem(this.storeKey, JSON.stringify(history));
	      return true;
	    }
	  }, {
	    key: "clear",
	    value: function clear() {
	      this.store.removeItem(this.storeKey);
	    }
	  }, {
	    key: "render",
	    value: function render() {
	      var html = [];
	      var history = this.load();
	      history.forEach(function (item) {
	        html.push(renderHistroyItem(item));
	      });
	      return html.join('');
	    }
	  }]);

	  return History;
	}();

	var arrayWithHoles = createCommonjsModule(function (module) {
	  function _arrayWithHoles(arr) {
	    if (Array.isArray(arr)) return arr;
	  }

	  module.exports = _arrayWithHoles;
	  module.exports["default"] = module.exports, module.exports.__esModule = true;
	});
	unwrapExports(arrayWithHoles);

	var iterableToArrayLimit = createCommonjsModule(function (module) {
	  function _iterableToArrayLimit(arr, i) {
	    var _i = arr && (typeof Symbol !== "undefined" && arr[Symbol.iterator] || arr["@@iterator"]);

	    if (_i == null) return;
	    var _arr = [];
	    var _n = true;
	    var _d = false;

	    var _s, _e;

	    try {
	      for (_i = _i.call(arr); !(_n = (_s = _i.next()).done); _n = true) {
	        _arr.push(_s.value);

	        if (i && _arr.length === i) break;
	      }
	    } catch (err) {
	      _d = true;
	      _e = err;
	    } finally {
	      try {
	        if (!_n && _i["return"] != null) _i["return"]();
	      } finally {
	        if (_d) throw _e;
	      }
	    }

	    return _arr;
	  }

	  module.exports = _iterableToArrayLimit;
	  module.exports["default"] = module.exports, module.exports.__esModule = true;
	});
	unwrapExports(iterableToArrayLimit);

	var arrayLikeToArray = createCommonjsModule(function (module) {
	  function _arrayLikeToArray(arr, len) {
	    if (len == null || len > arr.length) len = arr.length;

	    for (var i = 0, arr2 = new Array(len); i < len; i++) {
	      arr2[i] = arr[i];
	    }

	    return arr2;
	  }

	  module.exports = _arrayLikeToArray;
	  module.exports["default"] = module.exports, module.exports.__esModule = true;
	});
	unwrapExports(arrayLikeToArray);

	var unsupportedIterableToArray = createCommonjsModule(function (module) {
	  function _unsupportedIterableToArray(o, minLen) {
	    if (!o) return;
	    if (typeof o === "string") return arrayLikeToArray(o, minLen);
	    var n = Object.prototype.toString.call(o).slice(8, -1);
	    if (n === "Object" && o.constructor) n = o.constructor.name;
	    if (n === "Map" || n === "Set") return Array.from(o);
	    if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return arrayLikeToArray(o, minLen);
	  }

	  module.exports = _unsupportedIterableToArray;
	  module.exports["default"] = module.exports, module.exports.__esModule = true;
	});
	unwrapExports(unsupportedIterableToArray);

	var nonIterableRest = createCommonjsModule(function (module) {
	  function _nonIterableRest() {
	    throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.");
	  }

	  module.exports = _nonIterableRest;
	  module.exports["default"] = module.exports, module.exports.__esModule = true;
	});
	unwrapExports(nonIterableRest);

	var slicedToArray = createCommonjsModule(function (module) {
	  function _slicedToArray(arr, i) {
	    return arrayWithHoles(arr) || iterableToArrayLimit(arr, i) || unsupportedIterableToArray(arr, i) || nonIterableRest();
	  }

	  module.exports = _slicedToArray;
	  module.exports["default"] = module.exports, module.exports.__esModule = true;
	});
	var _slicedToArray = unwrapExports(slicedToArray);

	var handlers = {
	  search: function search() {
	    this.submit();
	  },
	  back: function back() {
	    var item = null;

	    if (this.targetValue) {
	      item = findFilterItemByName(this.target, this.targetValue);
	    }

	    this.input = '';
	    this.targetValue = '';

	    if (item) {
	      this.selectFilterValue(item.value);
	      this.clearTargetFilter(); // 移动输入框到筛选器列表的末尾

	      this.$tokens.append(this.$inputDropdown);
	    } else {
	      this.clearTargetFilter();
	    }

	    this.$input.focus();
	  },
	  apply: function apply(paramsStr) {
	    var params = JSON.parse(unescape(paramsStr));
	    this.active = true;
	    this.setData(params);
	    this.commit();
	  },
	  'clear-history': function clearHistory() {
	    this.history.clear();
	    this.buildInputDropdown();
	  }
	};
	function exec(_this, cmd) {
	  var i = cmd.indexOf('<cmd:');

	  if (i < 0) {
	    return false;
	  }

	  var _cmd$slice$split = cmd.slice(i + 5, -1).split(':'),
	      _cmd$slice$split2 = _slicedToArray(_cmd$slice$split, 2),
	      name = _cmd$slice$split2[0],
	      params = _cmd$slice$split2[1];

	  if (handlers[name]) {
	    handlers[name].call(_this, params);
	    return true;
	  }

	  return false;
	}

	var FilteredSearchBox =
	/*#__PURE__*/
	function (_Builder) {
	  _inherits(FilteredSearchBox, _Builder);

	  function FilteredSearchBox($el, options) {
	    var _this;

	    _classCallCheck(this, FilteredSearchBox);

	    var config = new Config(options);
	    _this = _possibleConstructorReturn(this, _getPrototypeOf(FilteredSearchBox).call(this));
	    _this.config = config;
	    _this.text = config.text;
	    _this.data = config.data();
	    _this.groups = config.groups;
	    _this.filters = config.filters;
	    _this.callback = config.callback;
	    _this.input = '';
	    _this.store = {};
	    _this.active = false;
	    _this.target = null;
	    _this.targetValue = null;
	    _this.history = new History(config.history);
	    _this.$el = $el;
	    _this.$search = null;
	    _this.$tokens = null;
	    _this.$target = null;
	    _this.$targetValues = null;
	    _this.logger = {
	      log: function log() {}
	    };

	    if (options.debug) {
	      _this.logger = console;
	    }

	    if (typeof _this.data.search !== 'string') {
	      _this.data.search = '';
	    }

	    _this.build();

	    bindEventHandlers(_assertThisInitialized(_this));
	    return _this;
	  } // 清空选择器的选项


	  _createClass(FilteredSearchBox, [{
	    key: "clearFilterValue",
	    value: function clearFilterValue() {
	      var filter = this.target;
	      var $token = this.$target;
	      var values = this.data[filter.key];
	      var $values = this.$targetValues.find('.value-container');

	      if (filter.multiple && values) {
	        $token.find('.value').each(function () {
	          var i;
	          var value = $(this).data('value');

	          if (typeof value === 'undefined') {
	            return;
	          }

	          value = value.toString();

	          for (i = 0; i < values.length; ++i) {
	            if (values[i].toString() === value) {
	              values.splice(i, 1);
	              break;
	            }
	          }
	        });

	        if (values.length < 1) {
	          delete this.data[filter.key];
	        }
	      } else {
	        delete this.data[filter.key];
	      }

	      $values.remove();
	      this.commit();
	      this.buildFilterDropdown(filter);
	    }
	    /**
	     * 清除筛选器依赖表里的筛选器
	     * 一个筛选器被其它筛选器依赖后，当这个筛选器的值被改变时，其它依赖筛选器也需要清除
	     * @param {Object} filterKey 筛选器标识
	     * @returns {Number} 清除的筛选器的数量
	     */

	  }, {
	    key: "clearRequiredFilters",
	    value: function clearRequiredFilters(filterKey) {
	      var that = this;
	      var count = 0;
	      that.filters.forEach(function (f) {
	        if (f.requires instanceof Array) {
	          if (f.requires.indexOf(filterKey) >= 0) {
	            that.removeFilter(f.key);
	            count += 1;
	          }
	        }
	      });
	      return count;
	    }
	    /**
	     * 为筛选选器选择一个选项
	     * @param {String} value 选项值
	     * @returns {Boolean} 是否成功选中
	     */

	  }, {
	    key: "selectFilterValue",
	    value: function selectFilterValue(value) {
	      var html;
	      var filter = this.target;
	      var $values = this.$targetValues;
	      var values = this.data[filter.key];

	      if (!$values) {
	        return false;
	      }

	      if (filter.multiple) {
	        if (values instanceof Array && values.indexOf(value.toString()) >= 0) {
	          return false;
	        }
	      } else if (values === value.toString()) {
	        return false;
	      }

	      html = this.renderFilterTokenValue(filter, value);

	      if (html) {
	        $values.append(html);

	        if (filter.multiple) {
	          if (this.data[filter.key] instanceof Array) {
	            this.data[filter.key].push(value);
	          } else {
	            this.data[filter.key] = [value];
	          }
	        } else {
	          this.data[filter.key] = value;
	        }

	        this.clearRequiredFilters(filter.key);
	        this.commit();
	        return true;
	      }

	      return false;
	    }
	    /**
	     * 移除当前筛选器中的一个选项标记
	     * @param {jQuery} $token 筛选器标记
	     * @param {String} value 筛选选项值
	     * @returns {Boolean} 是否移除成功
	     */

	  }, {
	    key: "removeFilterValue",
	    value: function removeFilterValue($token, value) {
	      var values;
	      var filter;
	      filter = this.getFilterByKey($token.data('key'));

	      if (!filter) {
	        return false;
	      }

	      $token.find('.value[data-value="' + value + '"]').parent().remove();
	      values = this.data[filter.key];

	      if (filter.multiple) {
	        value = value.toString();
	        values.some(function (v, i) {
	          if (v.toString() === value) {
	            values.splice(i, 1);
	            return true;
	          }

	          return false;
	        });
	      } else {
	        delete this.data[filter.key];
	      }

	      if (isEmptyFilterToken($token)) {
	        // 如果不是当前正编辑的筛选条件，则移除筛选器并取消编辑对象
	        if (!this.target || this.target.key !== filter.key) {
	          this.removeFilterToken($token);
	          this.clearTargetFilter();
	        }
	      }

	      this.clearRequiredFilters(filter.key);
	      this.buildInputDropdown();
	      this.commit();
	      return true;
	    }
	  }, {
	    key: "doRemoveFilter",
	    value: function doRemoveFilter(filterKey) {
	      var $token;
	      delete this.data[filterKey];
	      $token = this.$el.find('.js-visual-token[data-key="' + filterKey + '"]');
	      $token.remove();
	    }
	  }, {
	    key: "removeFilter",
	    value: function removeFilter(filterKey) {
	      this.doRemoveFilter(filterKey);
	      this.clearRequiredFilters(filterKey);
	      this.buildInputDropdown();
	      this.commit();
	    }
	    /**
	     * 移除一个筛选器标记元素
	     * @param {jQuery} $token 筛选器标记元素
	     */

	  }, {
	    key: "removeFilterToken",
	    value: function removeFilterToken($token) {
	      var key = $token.data('key');
	      var values = this.data[key];
	      var filter = this.getFilterByKey(key);

	      if (!filter) {
	        return false;
	      }

	      if (filter.type === 'daterange') {
	        delete this.data[key];
	      } else if (filter.multiple && values) {
	        $token.find('.value').each(function () {
	          var i;
	          var value = $(this).data('value');

	          if (typeof value === 'undefined') {
	            return;
	          }

	          value = value.toString();

	          for (i = 0; i < values.length; ++i) {
	            if (values[i].toString() === value) {
	              values.splice(i, 1);
	              break;
	            }
	          }
	        });

	        if (values.length < 1) {
	          delete this.data[key];
	        }
	      } else {
	        delete this.data[key];
	      }

	      $token.remove();
	      this.clearRequiredFilters(key);
	      this.buildInputDropdown();
	      this.commit();
	      return true;
	    }
	  }, {
	    key: "newFilter",
	    value: function newFilter(filterKey) {
	      var $token;
	      var filter = null;
	      this.logger.log('newFilter()', filterKey);
	      filter = this.getFilterByKey(filterKey);

	      if (!filter || !this.visibleFilter(filter)) {
	        return false;
	      }

	      $token = this.$el.find('[data-key="' + filterKey + '"]');

	      if ($token.length < 1) {
	        $token = $(this.renderVisualToken(filter));
	        $token.insertBefore(this.$inputDropdown);
	      }

	      this.selectFilterToken($token);
	      this.updateState();
	      return true;
	    } // 编辑搜索条件内容

	  }, {
	    key: "editTerm",
	    value: function editTerm() {
	      if (this.$search) {
	        this.$search.remove();
	      }

	      this.$search = null;
	      this.buildInputDropdown();
	      this.input = this.data.search;
	      this.data.search = '';
	      this.$input.val(this.input);
	      this.$input.focus();
	    }
	    /**
	     * 编辑筛选器
	     * @param {jQuery} $token 目标筛选器的标记元素
	     * @returns {Boolean} 是否成功切换编辑状态
	     */

	  }, {
	    key: "editFilter",
	    value: function editFilter($token) {
	      var filter = this.getFilterByKey($token.data('key'));

	      if (this.target && this.target.key === filter.key) {
	        this.$input.focus();
	        return true;
	      } // 如果当前有正编辑的筛选器，则保存它


	      if (this.targetValue) {
	        var item = findFilterItemByName(this.target, this.targetValue);

	        if (item) {
	          this.selectFilterValue(item.value);
	        }
	      }

	      this.logger.log('editFilter()');

	      if (this.selectFilterToken($token)) {
	        this.editCurrentFilterValue();
	        return true;
	      }

	      return false;
	    }
	  }, {
	    key: "editToken",
	    value: function editToken($token) {
	      if (isSearchTermToken($token)) {
	        this.editTerm();
	      } else {
	        this.editFilter($token);
	      }
	    }
	    /**
	     * 获取筛选器标记元素
	     * @param {Object} filter 筛选器对象
	     * @param {jQuery} $anchor 作为锚点的标记元素（可选），如果指定该参数，则会以它为起点，
	     * 在它前面的元素中查找匹配的筛选器标记元素。
	     */

	  }, {
	    key: "getFilterToken",
	    value: function getFilterToken(filter, $anchor) {
	      var $token;
	      var selector = '.js-visual-token[data-key="' + filter.key + '"]';

	      if ($anchor) {
	        $token = $anchor.prev(selector);
	      } else {
	        $token = this.$el.find(selector);
	      }

	      if ($token.length < 1) {
	        return null;
	      }

	      return $token.last();
	    }
	    /**
	     * 取出指定筛选器的一个选项
	     * @param {jQuery} $token 筛选器标记元素
	     * @returns {String} 取出的选项内容，如果没有则返回 null
	     */

	  }, {
	    key: "popFilterValue",
	    value: function popFilterValue($token) {
	      var value;
	      var item;
	      var filter = this.getFilterByKey($token.data('key'));

	      if (!filter) {
	        return null;
	      }

	      if (filter.type === 'daterange') {
	        $token.find('.value-container').remove();
	        value = this.data[filter.key];
	        delete this.data[filter.key];
	      } else {
	        if (filter.multiple) {
	          value = this.data[filter.key].pop();
	          $token.find('.value[data-value="' + value + '"]').parent().remove();
	        } else {
	          $token.find('.value-container').remove();
	          value = this.data[filter.key];
	          delete this.data[filter.key];
	        }

	        item = findFilterItemByValue(filter, value);

	        if (item) {
	          value = item.name;
	        } else if (_typeof(filter.none) === 'object') {
	          if (filter.none.value.toString() === value.toString()) {
	            value = filter.none.name;
	          }
	        }
	      }

	      this.logger.log('[' + filter.key + '] pop value:', value);
	      return value;
	    }
	    /**
	     * 取出当前选中筛选器的一个选项
	     * @returns {String} 取出的选项内容，如果没有则返回 null
	     */

	  }, {
	    key: "popCurrentFilterValue",
	    value: function popCurrentFilterValue() {
	      return this.popFilterValue(this.$target);
	    }
	    /**
	     * 取出当前选中筛选器的一个选项进行编辑
	     * @returns {String} 取出的选项内容，如果没有则返回 null
	     */

	  }, {
	    key: "editCurrentFilterValue",
	    value: function editCurrentFilterValue() {
	      var value = this.popCurrentFilterValue();

	      if (!value) {
	        return null;
	      }

	      this.targetValue = value; // 将输入框移动到目标筛选条件后面

	      this.$inputDropdown.insertAfter(this.$target);
	      this.buildInputDropdown();
	      this.$input.val(value).focus();
	      return value;
	    }
	    /**
	     * 选中一个筛选器，作为当前编辑对象
	     * @param {jQuery} $token 筛选器标记元素
	     * @return {Boolean} 是否选中成功
	     */

	  }, {
	    key: "selectFilterToken",
	    value: function selectFilterToken($token) {
	      var filter = this.getFilterByKey($token.data('key'));

	      if (!filter) {
	        return false;
	      }

	      if (this.target) {
	        if (this.target.key === filter.key) {
	          return true;
	        }
	      }

	      this.input = '';
	      this.target = filter;
	      this.$target = $token;
	      this.$targetValues = $token.find('.selectable'); // 将输入框定位到筛选器标记元素的后面

	      this.$inputDropdown.insertAfter($token);
	      this.buildFilterDropdown(this.target);
	      this.$input.focus();
	      return true;
	    }
	  }, {
	    key: "clearTargetFilter",
	    value: function clearTargetFilter() {
	      var that = this;
	      var picker;

	      if (that.target) {
	        if (isEmptyFilterToken(that.$target)) {
	          that.$target.remove();
	        }

	        if (that.target.type === 'daterange') {
	          picker = that.$input.data('daterangepicker');

	          if (picker) {
	            picker.remove();
	          }
	        }

	        that.applyInput();
	      }

	      that.target = null;
	      that.targetValue = '';
	      that.$target = null;
	      that.$targetValues = null;
	      that.buildInputDropdown();
	    }
	    /**
	     * 从远程加载筛选器选项列表
	     * @param {Object} filter 筛选器对象
	     * @param {function} callback 加载完后的回调
	     */

	  }, {
	    key: "loadFilterRemoteItems",
	    value: function loadFilterRemoteItems(filter, callback) {
	      var _this2 = this;

	      var store;
	      var cache;
	      var key = filter.key;

	      if (typeof filter.remote.params === 'function') {
	        key = JSON.stringify(filter.remote.params(this.data));
	      } else if (filter.remote.params) {
	        key = JSON.stringify(filter.remote.params);
	      }

	      store = this.store[filter.key];

	      if (_typeof(store) !== 'object') {
	        store = {
	          cache: {}
	        };
	        this.store[filter.key] = store;
	      }

	      store.key = key;
	      cache = store.cache[key];

	      if (_typeof(cache) !== 'object') {
	        cache = {
	          loading: true,
	          items: []
	        };
	        store.cache[key] = cache;
	      }

	      if (!cache.loading) {
	        filter.items = cache.items;
	        this.logger.log('[' + filter.key + '] use cached items');

	        if (callback) {
	          callback();
	        }

	        return;
	      }

	      if (Array.isArray(filter.remote)) {
	        filter.items = [];
	        var items = [];
	        var load = 0;
	        filter.remote.forEach(function (item) {
	          _this2.fetchItems(item, function (data) {
	            if (typeof item.converter === 'function') {
	              items = items.concat(item.converter(data));
	            } else {
	              items = items.concat(data);
	            }

	            load += 1;

	            if (load === filter.remote.length) {
	              cache.items = items;
	              filter.items = items;
	              cache.loading = false;

	              if (callback) {
	                callback();
	              }
	            }
	          }, function () {
	            store.loading = false;
	          });
	        });
	      } else {
	        this.fetchItems(filter.remote, function (data) {
	          if (typeof filter.remote.converter === 'function') {
	            cache.items = filter.remote.converter(data);
	          } else {
	            cache.items = data;
	          }

	          cache.loading = false;
	          filter.items = cache.items;

	          if (callback) {
	            callback();
	          }
	        }, function () {
	          store.loading = false;
	        });
	      }
	    }
	  }, {
	    key: "fetchItems",
	    value: function fetchItems(remoteData, successCallback, failCallback) {
	      var options = {
	        url: remoteData.url
	      };

	      if (typeof remoteData.params === 'function') {
	        options.data = remoteData.params(this.data);
	      } else if (remoteData.params) {
	        options.data = remoteData.params;
	      }

	      var fetcher = function fetcher(ajaxOptions, onSuccess, onError) {
	        return $.ajax(ajaxOptions).done(onSuccess).fail(onError);
	      };

	      if (typeof remoteData.fetcher === 'function') {
	        fetcher = remoteData.fetcher;
	      }

	      fetcher(options, function (data) {
	        successCallback(data);
	      }, function () {
	        failCallback();
	      });
	    }
	  }, {
	    key: "getCurrentFilterItem",
	    value: function getCurrentFilterItem(value) {
	      if (this.target && this.checkFilterItemsLoaded(this.target)) {
	        return findFilterItemByValue(this.target, value);
	      }

	      return false;
	    }
	  }, {
	    key: "execCommand",
	    value: function execCommand(cmd) {
	      return exec(this, cmd);
	    }
	  }, {
	    key: "removeDateRangePicker",
	    value: function removeDateRangePicker() {
	      var picker = this.$input.data('daterangepicker');

	      if (picker) {
	        picker.remove();
	      }

	      this.$input.off('apply.daterangepicker cancel.daterangepicker');
	    } // 应用当前输入的内容，更新元素

	  }, {
	    key: "applyInput",
	    value: function applyInput() {
	      this.logger.log('applyInput()', this.input);

	      if (this.data.search) {
	        this.data.search += this.input;
	      } else {
	        this.data.search = this.input;
	      } // 没有目标筛选器的话，就当成更新搜索条件


	      if (!this.target) {
	        this.buildSearchTerm();
	      }

	      this.$input.val('');
	      this.input = '';
	    }
	    /**
	     * 设置是否禁用此组件
	     * @param {Boolean} disabled 是否禁用
	     */

	  }, {
	    key: "setDisabled",
	    value: function setDisabled(disabled) {
	      this.$input.prop('disabled', disabled);

	      if (disabled) {
	        this.active = false;
	        this.$el.addClass('disabled');
	        this.$inputDropdown.addClass('disabled').dropdown('hide');
	      } else {
	        this.$el.removeClass('disabled');
	        this.$inputDropdown.removeClass('disabled');
	      }
	    }
	  }, {
	    key: "getFilterByName",
	    value: function getFilterByName(name) {
	      return findListItem(this.filters, function (f) {
	        return f.name === name;
	      });
	    }
	  }, {
	    key: "getFilterByKey",
	    value: function getFilterByKey(key) {
	      return findListItem(this.filters, function (f) {
	        return f.key === key;
	      });
	    }
	    /**
	     * 获取筛选器可用的选项列表
	     * @param {Object} filter 筛选器对象
	     */

	  }, {
	    key: "getFilterAvailableItems",
	    value: function getFilterAvailableItems(filter) {
	      var that = this;
	      var selectedItems = that.data[filter.key];

	      if (typeof selectedItems === 'undefined' || selectedItems.length < 1) {
	        return filter.items;
	      } // 如果是单选的筛选条件，只要选择一个选项，就不允许继续选了


	      if (!filter.multiple) {
	        return [];
	      }

	      if (_typeof(filter.none) === 'object') {
	        if (selectedItems[0].toString() === filter.none.value.toString()) {
	          return [];
	        }
	      }

	      return filter.items.filter(function (item) {
	        return !selectedItems.some(function (selected) {
	          return selected.toString() === item.value.toString();
	        });
	      });
	    }
	    /**
	     * 检查筛选器选项列表是否已经加载完毕
	     * @param {Object} filter 筛选器对象
	     */

	  }, {
	    key: "checkFilterItemsLoaded",
	    value: function checkFilterItemsLoaded(filter) {
	      var cache;
	      var store = this.store[filter.key];

	      if (_typeof(filter.remote) !== 'object') {
	        return true;
	      }

	      if (_typeof(store) === 'object' && store.key) {
	        cache = store.cache[store.key];

	        if (_typeof(cache) === 'object' && !cache.loading) {
	          return true;
	        }
	      }

	      return false;
	    } // 检查筛选器的值是否有效（排除“none”值）

	  }, {
	    key: "checkFilterValue",
	    value: function checkFilterValue(filterKey) {
	      var filter = this.getFilterByKey(filterKey);
	      var value = this.data[filterKey];

	      if (!value) {
	        return false;
	      }

	      if (_typeof(filter.none) === 'object') {
	        if (filter.multiple) {
	          value = value[0];
	        }

	        if (value.toString() === filter.none.value.toString()) {
	          return false;
	        }
	      }

	      return true;
	    } // 设置 tabs 选中

	  }, {
	    key: "setTabSelected",
	    value: function setTabSelected() {
	      for (var i = 0; i < this.target.tabs.length; i++) {
	        if (this.$el.find(".item[data-tab=".concat(this.target.tabs[i].key, "]")).not('.filtered').length) {
	          this.$el.find(".tab[data-tab=".concat(this.target.tabs[i].key, "]")).trigger('click');
	          break;
	        }
	      }
	    }
	    /**
	     * 检查筛选器是否可见
	     * 筛选器是否可见，取决于是否有可选的选项、是否满足依赖
	     * @param {Object} filter 筛选器对象
	     */

	  }, {
	    key: "visibleFilter",
	    value: function visibleFilter(filter) {
	      var i;
	      var value; // 如果这个筛选器依赖其它筛选器

	      if (filter.requires) {
	        if (typeof filter.requires === 'string') {
	          if (!this.checkFilterValue(filter.requires)) {
	            return false;
	          }
	        } else if (filter.requires instanceof Array) {
	          for (i = 0; i < filter.requires.length; ++i) {
	            if (!this.checkFilterValue(filter.requires[i])) {
	              return false;
	            }
	          }
	        }
	      }

	      if (filter.type === 'daterange') {
	        return !this.data[filter.key];
	      }

	      if (this.checkFilterItemsLoaded(filter)) {
	        if (this.getFilterAvailableItems(filter).length > 0) {
	          return true;
	        }

	        if (_typeof(filter.none) === 'object') {
	          value = this.data[filter.key];

	          if (!value || value.length < 1) {
	            return true;
	          }

	          if (filter.multiple) {
	            return value.indexOf(filter.none.value.toString()) === -1;
	          }

	          return value !== filter.none.value.toString();
	        }

	        return false;
	      }

	      return true;
	    }
	  }, {
	    key: "isEmpty",
	    value: function isEmpty() {
	      var that = this;
	      var emptyFilters = that.filters.every(function (filter) {
	        var value = that.data[filter.key];
	        return typeof value === 'undefined' || value.length < 1;
	      });
	      return emptyFilters && !this.data.search && !this.input;
	    } // 更新输入框内的占位符

	  }, {
	    key: "updatePlaceholder",
	    value: function updatePlaceholder() {
	      if (!this.isEmpty() || this.target) {
	        this.$input.attr('placeholder', '');
	      } else {
	        this.$input.attr('placeholder', this.text.placeholder);
	      }
	    } // 更新“清除”按钮的状态

	  }, {
	    key: "updateClearButton",
	    value: function updateClearButton() {
	      if (!this.isEmpty() || this.target || this.$input.val()) {
	        this.$el.removeClass('is-empty');
	      } else {
	        this.$el.addClass('is-empty');
	      }
	    }
	  }, {
	    key: "focus",
	    value: function focus() {
	      this.$input.focus();
	    }
	  }, {
	    key: "hasFocus",
	    value: function hasFocus() {
	      if (this.active || this.$input.is(':focus')) {
	        return true;
	      }

	      return false;
	    }
	    /**
	     * 隐藏下拉菜单时的回调
	     * @returns {Boolean} 是否需要隐藏
	     */

	  }, {
	    key: "onHide",
	    value: function onHide() {
	      return !this.hasFocus();
	    } // 锁定显示一段时间，避免下拉框自动隐藏

	  }, {
	    key: "lockShow",
	    value: function lockShow() {
	      var _this3 = this;

	      this.active = true; // 功能与 deferFocusTime() 互斥，所以取消它的定时器

	      if (this.timerForFocus) {
	        clearTimeout(this.timerForFocus);
	      }

	      this.timerForFocus = setTimeout(function () {
	        _this3.active = false;
	      }, 300);
	    } // 延长焦点状态时间，避免在做一些操作时因取消焦点而导致下拉框自动隐藏

	  }, {
	    key: "deferFocusTime",
	    value: function deferFocusTime() {
	      var _this4 = this;

	      if (this.active && this.timerForFocus) {
	        return;
	      }

	      if (this.timerForFocus) {
	        clearTimeout(this.timerForFocus);
	      }

	      this.active = true;
	      this.timerForFocus = setTimeout(function () {
	        _this4.active = false; // 如果输入框还未获得焦点，则隐藏下拉框

	        if (!_this4.$input.is(':focus')) {
	          _this4.$inputDropdown.dropdown('hide');
	        }
	      }, 200);
	    }
	  }, {
	    key: "resetInputPosition",
	    value: function resetInputPosition() {
	      var _this5 = this;

	      // 如果已经在末尾，就不重复变动了，避免下拉框重复收起和展开
	      if (this.$inputDropdown.is(':last-child')) {
	        return;
	      }

	      setTimeout(function () {
	        // 移动输入框到筛选器列表的末尾
	        _this5.$tokens.append(_this5.$inputDropdown);
	      }, 400);
	    }
	  }, {
	    key: "addHistory",
	    value: function addHistory(data) {
	      this.history.add(this.filters, data);
	      this.buildInputDropdown();
	    }
	  }, {
	    key: "generateHistoryItem",
	    value: function generateHistoryItem(data) {
	      return this.history.generateItem(this.filters, data);
	    }
	  }, {
	    key: "submit",
	    value: function submit() {
	      var that = this;
	      var data = {};
	      that.filters.forEach(function (f) {
	        var value = that.data[f.key];

	        if (typeof value !== 'undefined') {
	          data[f.key] = that.data[f.key];
	        }
	      });
	      that.applyInput();
	      data.search = that.data.search;
	      that.callback(cleanCopy(data));
	    }
	  }, {
	    key: "updateState",
	    value: function updateState() {
	      this.updatePlaceholder();
	      this.updateClearButton();
	    } // 提交当前的改动

	  }, {
	    key: "commit",
	    value: function commit() {
	      this.updateState();
	      this.$el.trigger('change.fsb', cleanCopy(this.data));
	    } // 清除全部筛选器

	  }, {
	    key: "clear",
	    value: function clear() {
	      this.$el.find('.js-visual-token').remove();
	      this.data = {};
	      this.input = '';
	      this.$input.val('');
	      this.clearTargetFilter();
	    } // 设置筛选器列表

	  }, {
	    key: "setFilters",
	    value: function setFilters(filters) {
	      var that = this;
	      var keys = filters.map(function (f) {
	        return f.key;
	      });
	      that.filters.forEach(function (f) {
	        if (keys.indexOf(f.key) < 0) {
	          that.removeFilter(f.key);
	        }
	      });
	      that.clearTargetFilter();
	      that.filters = filters;
	      that.filters.forEach(function (f) {
	        // 如果该筛选器使用的是远程的选项列表，且之前已经有缓存选项列表，则恢复它
	        if (_typeof(f.remote) === 'object' && that.checkFilterItemsLoaded(f)) {
	          that.loadFilterRemoteItems(f);
	        }
	      });
	      that.buildInputDropdown();
	    }
	    /**
	     * 设置选中的筛选条件
	     * @param {Object} data 筛选条件数据
	     */

	  }, {
	    key: "setData",
	    value: function setData(data) {
	      this.clear();
	      this.data = data;
	      this.buildFilterTokens();
	      this.buildInputDropdown();
	      this.buildSearchTerm();
	      this.updateState();
	    } // 销毁组件

	  }, {
	    key: "destroy",
	    value: function destroy() {
	      this.clear();
	      this.$el.off('click');
	      this.removeDateRangePicker();
	      unbindEventHandlers();
	    }
	  }]);

	  return FilteredSearchBox;
	}(Builder);

	/* eslint-disable no-param-reassign */

	$.fn.filteredSearchBox = function (options) {
	  var that = this.data('filteredsearchbox');

	  if (that) {
	    that.destroy();
	  }

	  this.data('filteredsearchbox', new FilteredSearchBox(this, options));
	  return this;
	};

	var runtime_1 = createCommonjsModule(function (module) {
	  /**
	   * Copyright (c) 2014-present, Facebook, Inc.
	   *
	   * This source code is licensed under the MIT license found in the
	   * LICENSE file in the root directory of this source tree.
	   */
	  var runtime = function (exports) {

	    var Op = Object.prototype;
	    var hasOwn = Op.hasOwnProperty;
	    var undefined$1; // More compressible than void 0.

	    var $Symbol = typeof Symbol === "function" ? Symbol : {};
	    var iteratorSymbol = $Symbol.iterator || "@@iterator";
	    var asyncIteratorSymbol = $Symbol.asyncIterator || "@@asyncIterator";
	    var toStringTagSymbol = $Symbol.toStringTag || "@@toStringTag";

	    function define(obj, key, value) {
	      Object.defineProperty(obj, key, {
	        value: value,
	        enumerable: true,
	        configurable: true,
	        writable: true
	      });
	      return obj[key];
	    }

	    try {
	      // IE 8 has a broken Object.defineProperty that only works on DOM objects.
	      define({}, "");
	    } catch (err) {
	      define = function (obj, key, value) {
	        return obj[key] = value;
	      };
	    }

	    function wrap(innerFn, outerFn, self, tryLocsList) {
	      // If outerFn provided and outerFn.prototype is a Generator, then outerFn.prototype instanceof Generator.
	      var protoGenerator = outerFn && outerFn.prototype instanceof Generator ? outerFn : Generator;
	      var generator = Object.create(protoGenerator.prototype);
	      var context = new Context(tryLocsList || []); // The ._invoke method unifies the implementations of the .next,
	      // .throw, and .return methods.

	      generator._invoke = makeInvokeMethod(innerFn, self, context);
	      return generator;
	    }

	    exports.wrap = wrap; // Try/catch helper to minimize deoptimizations. Returns a completion
	    // record like context.tryEntries[i].completion. This interface could
	    // have been (and was previously) designed to take a closure to be
	    // invoked without arguments, but in all the cases we care about we
	    // already have an existing method we want to call, so there's no need
	    // to create a new function object. We can even get away with assuming
	    // the method takes exactly one argument, since that happens to be true
	    // in every case, so we don't have to touch the arguments object. The
	    // only additional allocation required is the completion record, which
	    // has a stable shape and so hopefully should be cheap to allocate.

	    function tryCatch(fn, obj, arg) {
	      try {
	        return {
	          type: "normal",
	          arg: fn.call(obj, arg)
	        };
	      } catch (err) {
	        return {
	          type: "throw",
	          arg: err
	        };
	      }
	    }

	    var GenStateSuspendedStart = "suspendedStart";
	    var GenStateSuspendedYield = "suspendedYield";
	    var GenStateExecuting = "executing";
	    var GenStateCompleted = "completed"; // Returning this object from the innerFn has the same effect as
	    // breaking out of the dispatch switch statement.

	    var ContinueSentinel = {}; // Dummy constructor functions that we use as the .constructor and
	    // .constructor.prototype properties for functions that return Generator
	    // objects. For full spec compliance, you may wish to configure your
	    // minifier not to mangle the names of these two functions.

	    function Generator() {}

	    function GeneratorFunction() {}

	    function GeneratorFunctionPrototype() {} // This is a polyfill for %IteratorPrototype% for environments that
	    // don't natively support it.


	    var IteratorPrototype = {};

	    IteratorPrototype[iteratorSymbol] = function () {
	      return this;
	    };

	    var getProto = Object.getPrototypeOf;
	    var NativeIteratorPrototype = getProto && getProto(getProto(values([])));

	    if (NativeIteratorPrototype && NativeIteratorPrototype !== Op && hasOwn.call(NativeIteratorPrototype, iteratorSymbol)) {
	      // This environment has a native %IteratorPrototype%; use it instead
	      // of the polyfill.
	      IteratorPrototype = NativeIteratorPrototype;
	    }

	    var Gp = GeneratorFunctionPrototype.prototype = Generator.prototype = Object.create(IteratorPrototype);
	    GeneratorFunction.prototype = Gp.constructor = GeneratorFunctionPrototype;
	    GeneratorFunctionPrototype.constructor = GeneratorFunction;
	    GeneratorFunction.displayName = define(GeneratorFunctionPrototype, toStringTagSymbol, "GeneratorFunction"); // Helper for defining the .next, .throw, and .return methods of the
	    // Iterator interface in terms of a single ._invoke method.

	    function defineIteratorMethods(prototype) {
	      ["next", "throw", "return"].forEach(function (method) {
	        define(prototype, method, function (arg) {
	          return this._invoke(method, arg);
	        });
	      });
	    }

	    exports.isGeneratorFunction = function (genFun) {
	      var ctor = typeof genFun === "function" && genFun.constructor;
	      return ctor ? ctor === GeneratorFunction || // For the native GeneratorFunction constructor, the best we can
	      // do is to check its .name property.
	      (ctor.displayName || ctor.name) === "GeneratorFunction" : false;
	    };

	    exports.mark = function (genFun) {
	      if (Object.setPrototypeOf) {
	        Object.setPrototypeOf(genFun, GeneratorFunctionPrototype);
	      } else {
	        genFun.__proto__ = GeneratorFunctionPrototype;
	        define(genFun, toStringTagSymbol, "GeneratorFunction");
	      }

	      genFun.prototype = Object.create(Gp);
	      return genFun;
	    }; // Within the body of any async function, `await x` is transformed to
	    // `yield regeneratorRuntime.awrap(x)`, so that the runtime can test
	    // `hasOwn.call(value, "__await")` to determine if the yielded value is
	    // meant to be awaited.


	    exports.awrap = function (arg) {
	      return {
	        __await: arg
	      };
	    };

	    function AsyncIterator(generator, PromiseImpl) {
	      function invoke(method, arg, resolve, reject) {
	        var record = tryCatch(generator[method], generator, arg);

	        if (record.type === "throw") {
	          reject(record.arg);
	        } else {
	          var result = record.arg;
	          var value = result.value;

	          if (value && typeof value === "object" && hasOwn.call(value, "__await")) {
	            return PromiseImpl.resolve(value.__await).then(function (value) {
	              invoke("next", value, resolve, reject);
	            }, function (err) {
	              invoke("throw", err, resolve, reject);
	            });
	          }

	          return PromiseImpl.resolve(value).then(function (unwrapped) {
	            // When a yielded Promise is resolved, its final value becomes
	            // the .value of the Promise<{value,done}> result for the
	            // current iteration.
	            result.value = unwrapped;
	            resolve(result);
	          }, function (error) {
	            // If a rejected Promise was yielded, throw the rejection back
	            // into the async generator function so it can be handled there.
	            return invoke("throw", error, resolve, reject);
	          });
	        }
	      }

	      var previousPromise;

	      function enqueue(method, arg) {
	        function callInvokeWithMethodAndArg() {
	          return new PromiseImpl(function (resolve, reject) {
	            invoke(method, arg, resolve, reject);
	          });
	        }

	        return previousPromise = // If enqueue has been called before, then we want to wait until
	        // all previous Promises have been resolved before calling invoke,
	        // so that results are always delivered in the correct order. If
	        // enqueue has not been called before, then it is important to
	        // call invoke immediately, without waiting on a callback to fire,
	        // so that the async generator function has the opportunity to do
	        // any necessary setup in a predictable way. This predictability
	        // is why the Promise constructor synchronously invokes its
	        // executor callback, and why async functions synchronously
	        // execute code before the first await. Since we implement simple
	        // async functions in terms of async generators, it is especially
	        // important to get this right, even though it requires care.
	        previousPromise ? previousPromise.then(callInvokeWithMethodAndArg, // Avoid propagating failures to Promises returned by later
	        // invocations of the iterator.
	        callInvokeWithMethodAndArg) : callInvokeWithMethodAndArg();
	      } // Define the unified helper method that is used to implement .next,
	      // .throw, and .return (see defineIteratorMethods).


	      this._invoke = enqueue;
	    }

	    defineIteratorMethods(AsyncIterator.prototype);

	    AsyncIterator.prototype[asyncIteratorSymbol] = function () {
	      return this;
	    };

	    exports.AsyncIterator = AsyncIterator; // Note that simple async functions are implemented on top of
	    // AsyncIterator objects; they just return a Promise for the value of
	    // the final result produced by the iterator.

	    exports.async = function (innerFn, outerFn, self, tryLocsList, PromiseImpl) {
	      if (PromiseImpl === void 0) PromiseImpl = Promise;
	      var iter = new AsyncIterator(wrap(innerFn, outerFn, self, tryLocsList), PromiseImpl);
	      return exports.isGeneratorFunction(outerFn) ? iter // If outerFn is a generator, return the full iterator.
	      : iter.next().then(function (result) {
	        return result.done ? result.value : iter.next();
	      });
	    };

	    function makeInvokeMethod(innerFn, self, context) {
	      var state = GenStateSuspendedStart;
	      return function invoke(method, arg) {
	        if (state === GenStateExecuting) {
	          throw new Error("Generator is already running");
	        }

	        if (state === GenStateCompleted) {
	          if (method === "throw") {
	            throw arg;
	          } // Be forgiving, per 25.3.3.3.3 of the spec:
	          // https://people.mozilla.org/~jorendorff/es6-draft.html#sec-generatorresume


	          return doneResult();
	        }

	        context.method = method;
	        context.arg = arg;

	        while (true) {
	          var delegate = context.delegate;

	          if (delegate) {
	            var delegateResult = maybeInvokeDelegate(delegate, context);

	            if (delegateResult) {
	              if (delegateResult === ContinueSentinel) continue;
	              return delegateResult;
	            }
	          }

	          if (context.method === "next") {
	            // Setting context._sent for legacy support of Babel's
	            // function.sent implementation.
	            context.sent = context._sent = context.arg;
	          } else if (context.method === "throw") {
	            if (state === GenStateSuspendedStart) {
	              state = GenStateCompleted;
	              throw context.arg;
	            }

	            context.dispatchException(context.arg);
	          } else if (context.method === "return") {
	            context.abrupt("return", context.arg);
	          }

	          state = GenStateExecuting;
	          var record = tryCatch(innerFn, self, context);

	          if (record.type === "normal") {
	            // If an exception is thrown from innerFn, we leave state ===
	            // GenStateExecuting and loop back for another invocation.
	            state = context.done ? GenStateCompleted : GenStateSuspendedYield;

	            if (record.arg === ContinueSentinel) {
	              continue;
	            }

	            return {
	              value: record.arg,
	              done: context.done
	            };
	          } else if (record.type === "throw") {
	            state = GenStateCompleted; // Dispatch the exception by looping back around to the
	            // context.dispatchException(context.arg) call above.

	            context.method = "throw";
	            context.arg = record.arg;
	          }
	        }
	      };
	    } // Call delegate.iterator[context.method](context.arg) and handle the
	    // result, either by returning a { value, done } result from the
	    // delegate iterator, or by modifying context.method and context.arg,
	    // setting context.delegate to null, and returning the ContinueSentinel.


	    function maybeInvokeDelegate(delegate, context) {
	      var method = delegate.iterator[context.method];

	      if (method === undefined$1) {
	        // A .throw or .return when the delegate iterator has no .throw
	        // method always terminates the yield* loop.
	        context.delegate = null;

	        if (context.method === "throw") {
	          // Note: ["return"] must be used for ES3 parsing compatibility.
	          if (delegate.iterator["return"]) {
	            // If the delegate iterator has a return method, give it a
	            // chance to clean up.
	            context.method = "return";
	            context.arg = undefined$1;
	            maybeInvokeDelegate(delegate, context);

	            if (context.method === "throw") {
	              // If maybeInvokeDelegate(context) changed context.method from
	              // "return" to "throw", let that override the TypeError below.
	              return ContinueSentinel;
	            }
	          }

	          context.method = "throw";
	          context.arg = new TypeError("The iterator does not provide a 'throw' method");
	        }

	        return ContinueSentinel;
	      }

	      var record = tryCatch(method, delegate.iterator, context.arg);

	      if (record.type === "throw") {
	        context.method = "throw";
	        context.arg = record.arg;
	        context.delegate = null;
	        return ContinueSentinel;
	      }

	      var info = record.arg;

	      if (!info) {
	        context.method = "throw";
	        context.arg = new TypeError("iterator result is not an object");
	        context.delegate = null;
	        return ContinueSentinel;
	      }

	      if (info.done) {
	        // Assign the result of the finished delegate to the temporary
	        // variable specified by delegate.resultName (see delegateYield).
	        context[delegate.resultName] = info.value; // Resume execution at the desired location (see delegateYield).

	        context.next = delegate.nextLoc; // If context.method was "throw" but the delegate handled the
	        // exception, let the outer generator proceed normally. If
	        // context.method was "next", forget context.arg since it has been
	        // "consumed" by the delegate iterator. If context.method was
	        // "return", allow the original .return call to continue in the
	        // outer generator.

	        if (context.method !== "return") {
	          context.method = "next";
	          context.arg = undefined$1;
	        }
	      } else {
	        // Re-yield the result returned by the delegate method.
	        return info;
	      } // The delegate iterator is finished, so forget it and continue with
	      // the outer generator.


	      context.delegate = null;
	      return ContinueSentinel;
	    } // Define Generator.prototype.{next,throw,return} in terms of the
	    // unified ._invoke helper method.


	    defineIteratorMethods(Gp);
	    define(Gp, toStringTagSymbol, "Generator"); // A Generator should always return itself as the iterator object when the
	    // @@iterator function is called on it. Some browsers' implementations of the
	    // iterator prototype chain incorrectly implement this, causing the Generator
	    // object to not be returned from this call. This ensures that doesn't happen.
	    // See https://github.com/facebook/regenerator/issues/274 for more details.

	    Gp[iteratorSymbol] = function () {
	      return this;
	    };

	    Gp.toString = function () {
	      return "[object Generator]";
	    };

	    function pushTryEntry(locs) {
	      var entry = {
	        tryLoc: locs[0]
	      };

	      if (1 in locs) {
	        entry.catchLoc = locs[1];
	      }

	      if (2 in locs) {
	        entry.finallyLoc = locs[2];
	        entry.afterLoc = locs[3];
	      }

	      this.tryEntries.push(entry);
	    }

	    function resetTryEntry(entry) {
	      var record = entry.completion || {};
	      record.type = "normal";
	      delete record.arg;
	      entry.completion = record;
	    }

	    function Context(tryLocsList) {
	      // The root entry object (effectively a try statement without a catch
	      // or a finally block) gives us a place to store values thrown from
	      // locations where there is no enclosing try statement.
	      this.tryEntries = [{
	        tryLoc: "root"
	      }];
	      tryLocsList.forEach(pushTryEntry, this);
	      this.reset(true);
	    }

	    exports.keys = function (object) {
	      var keys = [];

	      for (var key in object) {
	        keys.push(key);
	      }

	      keys.reverse(); // Rather than returning an object with a next method, we keep
	      // things simple and return the next function itself.

	      return function next() {
	        while (keys.length) {
	          var key = keys.pop();

	          if (key in object) {
	            next.value = key;
	            next.done = false;
	            return next;
	          }
	        } // To avoid creating an additional object, we just hang the .value
	        // and .done properties off the next function object itself. This
	        // also ensures that the minifier will not anonymize the function.


	        next.done = true;
	        return next;
	      };
	    };

	    function values(iterable) {
	      if (iterable) {
	        var iteratorMethod = iterable[iteratorSymbol];

	        if (iteratorMethod) {
	          return iteratorMethod.call(iterable);
	        }

	        if (typeof iterable.next === "function") {
	          return iterable;
	        }

	        if (!isNaN(iterable.length)) {
	          var i = -1,
	              next = function next() {
	            while (++i < iterable.length) {
	              if (hasOwn.call(iterable, i)) {
	                next.value = iterable[i];
	                next.done = false;
	                return next;
	              }
	            }

	            next.value = undefined$1;
	            next.done = true;
	            return next;
	          };

	          return next.next = next;
	        }
	      } // Return an iterator with no values.


	      return {
	        next: doneResult
	      };
	    }

	    exports.values = values;

	    function doneResult() {
	      return {
	        value: undefined$1,
	        done: true
	      };
	    }

	    Context.prototype = {
	      constructor: Context,
	      reset: function (skipTempReset) {
	        this.prev = 0;
	        this.next = 0; // Resetting context._sent for legacy support of Babel's
	        // function.sent implementation.

	        this.sent = this._sent = undefined$1;
	        this.done = false;
	        this.delegate = null;
	        this.method = "next";
	        this.arg = undefined$1;
	        this.tryEntries.forEach(resetTryEntry);

	        if (!skipTempReset) {
	          for (var name in this) {
	            // Not sure about the optimal order of these conditions:
	            if (name.charAt(0) === "t" && hasOwn.call(this, name) && !isNaN(+name.slice(1))) {
	              this[name] = undefined$1;
	            }
	          }
	        }
	      },
	      stop: function () {
	        this.done = true;
	        var rootEntry = this.tryEntries[0];
	        var rootRecord = rootEntry.completion;

	        if (rootRecord.type === "throw") {
	          throw rootRecord.arg;
	        }

	        return this.rval;
	      },
	      dispatchException: function (exception) {
	        if (this.done) {
	          throw exception;
	        }

	        var context = this;

	        function handle(loc, caught) {
	          record.type = "throw";
	          record.arg = exception;
	          context.next = loc;

	          if (caught) {
	            // If the dispatched exception was caught by a catch block,
	            // then let that catch block handle the exception normally.
	            context.method = "next";
	            context.arg = undefined$1;
	          }

	          return !!caught;
	        }

	        for (var i = this.tryEntries.length - 1; i >= 0; --i) {
	          var entry = this.tryEntries[i];
	          var record = entry.completion;

	          if (entry.tryLoc === "root") {
	            // Exception thrown outside of any try block that could handle
	            // it, so set the completion value of the entire function to
	            // throw the exception.
	            return handle("end");
	          }

	          if (entry.tryLoc <= this.prev) {
	            var hasCatch = hasOwn.call(entry, "catchLoc");
	            var hasFinally = hasOwn.call(entry, "finallyLoc");

	            if (hasCatch && hasFinally) {
	              if (this.prev < entry.catchLoc) {
	                return handle(entry.catchLoc, true);
	              } else if (this.prev < entry.finallyLoc) {
	                return handle(entry.finallyLoc);
	              }
	            } else if (hasCatch) {
	              if (this.prev < entry.catchLoc) {
	                return handle(entry.catchLoc, true);
	              }
	            } else if (hasFinally) {
	              if (this.prev < entry.finallyLoc) {
	                return handle(entry.finallyLoc);
	              }
	            } else {
	              throw new Error("try statement without catch or finally");
	            }
	          }
	        }
	      },
	      abrupt: function (type, arg) {
	        for (var i = this.tryEntries.length - 1; i >= 0; --i) {
	          var entry = this.tryEntries[i];

	          if (entry.tryLoc <= this.prev && hasOwn.call(entry, "finallyLoc") && this.prev < entry.finallyLoc) {
	            var finallyEntry = entry;
	            break;
	          }
	        }

	        if (finallyEntry && (type === "break" || type === "continue") && finallyEntry.tryLoc <= arg && arg <= finallyEntry.finallyLoc) {
	          // Ignore the finally entry if control is not jumping to a
	          // location outside the try/catch block.
	          finallyEntry = null;
	        }

	        var record = finallyEntry ? finallyEntry.completion : {};
	        record.type = type;
	        record.arg = arg;

	        if (finallyEntry) {
	          this.method = "next";
	          this.next = finallyEntry.finallyLoc;
	          return ContinueSentinel;
	        }

	        return this.complete(record);
	      },
	      complete: function (record, afterLoc) {
	        if (record.type === "throw") {
	          throw record.arg;
	        }

	        if (record.type === "break" || record.type === "continue") {
	          this.next = record.arg;
	        } else if (record.type === "return") {
	          this.rval = this.arg = record.arg;
	          this.method = "return";
	          this.next = "end";
	        } else if (record.type === "normal" && afterLoc) {
	          this.next = afterLoc;
	        }

	        return ContinueSentinel;
	      },
	      finish: function (finallyLoc) {
	        for (var i = this.tryEntries.length - 1; i >= 0; --i) {
	          var entry = this.tryEntries[i];

	          if (entry.finallyLoc === finallyLoc) {
	            this.complete(entry.completion, entry.afterLoc);
	            resetTryEntry(entry);
	            return ContinueSentinel;
	          }
	        }
	      },
	      "catch": function (tryLoc) {
	        for (var i = this.tryEntries.length - 1; i >= 0; --i) {
	          var entry = this.tryEntries[i];

	          if (entry.tryLoc === tryLoc) {
	            var record = entry.completion;

	            if (record.type === "throw") {
	              var thrown = record.arg;
	              resetTryEntry(entry);
	            }

	            return thrown;
	          }
	        } // The context.catch method must only be called with a location
	        // argument that corresponds to a known catch block.


	        throw new Error("illegal catch attempt");
	      },
	      delegateYield: function (iterable, resultName, nextLoc) {
	        this.delegate = {
	          iterator: values(iterable),
	          resultName: resultName,
	          nextLoc: nextLoc
	        };

	        if (this.method === "next") {
	          // Deliberately forget the last sent value so that we don't
	          // accidentally pass it on to the delegate.
	          this.arg = undefined$1;
	        }

	        return ContinueSentinel;
	      }
	    }; // Regardless of whether this script is executing as a CommonJS module
	    // or not, return the runtime object so that we can declare the variable
	    // regeneratorRuntime in the outer scope, which allows this module to be
	    // injected easily by `bin/regenerator --include-runtime script.js`.

	    return exports;
	  }( // If this script is executing as a CommonJS module, use module.exports
	  // as the regeneratorRuntime namespace. Otherwise create a new empty
	  // object. Either way, the resulting object will be used to initialize
	  // the regeneratorRuntime variable at the top of this file.
	   module.exports );

	  try {
	    regeneratorRuntime = runtime;
	  } catch (accidentalStrictMode) {
	    // This module should not be running in strict mode, so the above
	    // assignment should always work unless something is misconfigured. Just
	    // in case runtime.js accidentally runs in strict mode, we can escape
	    // strict mode using a global Function call. This could conceivably fail
	    // if a Content Security Policy forbids using Function, but in that case
	    // the proper solution is to fix the accidental strict mode problem. If
	    // you've misconfigured your bundler to force strict mode and applied a
	    // CSP to forbid Function, and you're not willing to fix either of those
	    // problems, please detail your unique predicament in a GitHub issue.
	    Function("r", "regeneratorRuntime = r")(runtime);
	  }
	});

	var regenerator = runtime_1;

	var htmlSafe = function () {
	  var $el = $('<div/>');
	  return function (text) {
	    return $el.text(text).html();
	  };
	}();

	var defaults$1 = {
	  readonly: false,
	  key: 'state',
	  name: 'board',
	  message: {
	    loading: 'loading ...',
	    stateDisabled: 'Current issue cannot switch to this state',
	    allComplete: 'Showing all issues',
	    empty: 'There are no issues here',
	    btnSetFirst: 'Move it to the first',
	    btnSetLast: 'Move it to the last'
	  },
	  className: {
	    iconComment: 'icon comments outline',
	    iconAngleLeft: 'icon angle double left',
	    iconAngleRight: 'icon angle double right',
	    iconIssue: 'icon sticky note outline',
	    card: 'ui link card',
	    action: 'ui button',
	    actions: 'ui mini basic icon buttons',
	    avatar: 'ui avatar image'
	  },
	  labelsTemplate: function labelsTemplate(label) {
	    return " <span class=\"label\" style=\"background-color: #".concat(label.color, "; color: #fff\">\n    ").concat(htmlSafe(label.name), "\n  </span>");
	  },
	  actions: function actions(config) {
	    if (!config.plugins.Sortable) {
	      return [];
	    }

	    return [{
	      id: 'btn-set-first',
	      "class": config.className.action,
	      icon: config.className.iconAngleLeft,
	      title: config.message.btnSetFirst,
	      callback: function callback(boards, board) {
	        var state = board.state.toString();
	        var states = boards.sortable.toArray();
	        var i = states.indexOf(state);

	        if (i >= 0) {
	          states.splice(i, 1);
	          states.splice(0, 0, state);
	          boards.sortable.sort(states);
	          config.onSorted(states);
	          boards.load();
	        }
	      }
	    }, {
	      id: 'btn-set-last',
	      "class": config.className.action,
	      icon: config.className.iconAngleRight,
	      title: config.message.btnSetLast,
	      callback: function callback(boards, board) {
	        var state = board.state.toString();
	        var states = boards.sortable.toArray();
	        var i = states.indexOf(state);

	        if (i >= 0) {
	          states.splice(i, 1);
	          states.push(state);
	          boards.sortable.sort(states);
	          config.onSorted(states);
	          boards.load();
	        }
	      }
	    }];
	  },
	  data: [{
	    order: 1,
	    name: 'Backlog',
	    state: 'open',
	    color: '#ffa726',
	    issuesCount: 0
	  }, {
	    order: 2,
	    name: 'Done',
	    state: 'closed',
	    color: '#2baf2b',
	    issuesCount: 0
	  }],
	  plugins: {},
	  types: [],
	  user: {
	    id: 0,
	    admin: false
	  },

	  /**
	   * 在任务列表加载完后的回调
	   * @callback BoardLoadCallback
	   * @param {Array} issues 任务列表
	   * @param {Number} count 任务总数
	   */

	  /**
	   * 在开始加载任务列表时的回调
	   * @param {Object,Board} board 板块对象
	   * @param {BoardLoadCallback} callback 用于接收任务列表的回调函数
	   */
	  onLoad: function onLoad(board, callback) {
	    $.ajax({
	      url: 'issues',
	      data: {
	        state: board.state,
	        page: board.page
	      }
	    }).done(function () {
	      callback([], 0);
	    }).fail(function () {
	      callback([], 0);
	    });
	  },

	  /**
	   * 在更新任务时的回调
	   * @param {Object} issue 任务
	   * @param {String,Number} oldState 更新前的状态
	   */
	  onUpdate: function onUpdate(issue, oldState) {
	    var _this = this;

	    $.ajax({
	      type: 'PUT',
	      url: issue.url,
	      data: {
	        state: issue.state
	      }
	    }).done(function (res) {
	      _this.updateIssue(res);
	    }).fail(function () {
	      _this.setIssueState(issue.id, oldState);
	    });
	  },

	  /**
	   * 在渲染任务卡片时的回调
	   * @param {Object} issue 任务
	   * @param {JQuery} $el 任务卡片
	   */
	  onRender: function onRender(issue, $el) {
	    $el.addClass("issue-state-".concat(issue.state));
	    return $el;
	  },

	  /**
	   * 在板块被排序后的回调
	   * @param {Array} states 状态列表
	   */
	  onSorted: function onSorted(states) {
	    window.console.log(states);
	  }
	};
	var Config$1 = function Config(config) {
	  _classCallCheck(this, Config);

	  $.extend(this, defaults$1, config);

	  if (config.className) {
	    this.className = $.extend({}, defaults$1.className, config.className);
	  }

	  if (config.message) {
	    this.message = $.extend({}, defaults$1.message, config.message);
	  }
	};

	var Renderer$1 =
	/*#__PURE__*/
	function () {
	  function Renderer(config) {
	    _classCallCheck(this, Renderer);

	    this.config = config;
	  }

	  _createClass(Renderer, [{
	    key: "getAvatarUrl",
	    value: function getAvatarUrl(name, avatarUrl) {
	      var Avatar = this.config.plugins.LetterAvatar;

	      if (!avatarUrl || avatarUrl.indexOf('no_portrait.png') === 0) {
	        if (Avatar) {
	          return Avatar(name);
	        }
	      }

	      return avatarUrl;
	    }
	  }, {
	    key: "getCardId",
	    value: function getCardId(issue) {
	      if (this.config.getIusseId) {
	        return this.config.getIusseId(issue);
	      }

	      return 'issue-card-' + issue.id;
	    }
	  }]);

	  return Renderer;
	}();

	/* eslint-disable indent */

	function getUserUrl(user) {
	  return user.html_url || user.path;
	}

	function renderCardUserLabel(issue) {
	  if (!issue.author) {
	    return '';
	  }

	  if (typeof issue.author.is_member !== 'undefined') {
	    if (!issue.author.is_member) {
	      return '<span class="user-label blue">[访客]</span>';
	    }
	  }

	  if (issue.author.outsourced) {
	    return '<span class="user-label red">[外包]</span>';
	  }

	  return '';
	}

	function renderCardLabels(issue, labelsTemplate) {
	  if (!issue.labels || !labelsTemplate) {
	    return '';
	  }

	  var html = issue.labels.map(labelsTemplate).join('');
	  return "<div class=\"labels\">".concat(html, "</div>");
	}

	var CardRenderer =
	/*#__PURE__*/
	function (_Renderer) {
	  _inherits(CardRenderer, _Renderer);

	  function CardRenderer() {
	    _classCallCheck(this, CardRenderer);

	    return _possibleConstructorReturn(this, _getPrototypeOf(CardRenderer).apply(this, arguments));
	  }

	  _createClass(CardRenderer, [{
	    key: "render",
	    value: function render(issue) {
	      var user = this.config.user;
	      var readonly = this.config.readonly;
	      var draggable = '';
	      var cardClass = this.config.className.card;

	      if (!readonly && (user.admin || user.id === issue.author.id)) {
	        draggable = 'draggable="true"';
	        cardClass += ' card-draggable';
	      }

	      return "<li class=\"".concat(cardClass, "\" ").concat(draggable, "\n      id=\"").concat(this.config.name, "-issue-").concat(issue.id, "\" data-id=\"").concat(issue.id, "\">\n      <div class=\"content\">\n        <a class=\"ui small header card-header\" href=\"").concat(issue.html_url, "\"\n        title=\"").concat(htmlSafe(issue.title), "\" target=\"_blank\">\n          ").concat(htmlSafe(issue.title), "\n        </a>\n        ").concat(this.config.topLevelLabel && this.config.topLevelLabel(issue) || '', "\n        ").concat(this.config.priorityLabel && this.config.priorityLabel(issue) || '', "\n      </div>\n      <div class=\"extra content\">\n        ").concat(this.renderAssignee(issue), "\n        ").concat(this.renderState(issue), "\n        ").concat(renderCardLabels(issue, this.config.labelsTemplate), "\n        <span class=\"card-number\">#").concat(issue.number, "</span>\n        ").concat(renderCardUserLabel(issue), "\n        ").concat(this.renderComments(issue), "\n      </div>\n    </li>");
	    }
	  }, {
	    key: "renderState",
	    value: function renderState(issue) {
	      var state = issue.state_data;

	      if (!state || this.config.key === 'state') {
	        return '';
	      }

	      return "<div class=\"state\">\n      <i title=\"".concat(state.name, "\" class=\"").concat(state.icon, "\" style=\"color: ").concat(state.color, "\"></i>\n    </div>");
	    }
	  }, {
	    key: "renderAssignee",
	    value: function renderAssignee(issue) {
	      var user = issue.assignee;

	      if (!user || !user.id || this.config.key !== 'state') {
	        return '';
	      }

	      return "<div class=\"assignee\">\n        <a target=\"_blank\" href=\"".concat(getUserUrl(user), "\" title=\"").concat(htmlSafe(user.name), "\">\n          <img src=\"").concat(this.getAvatarUrl(user.name, user.avatar_url), "\"\n            alt=\"").concat(htmlSafe(user.name), "\" class=\"").concat(this.config.className.avatar, "\">\n        </a>\n      </div>");
	    }
	  }, {
	    key: "renderComments",
	    value: function renderComments(issue) {
	      var className = this.config.className.iconComment;

	      if (!issue.comments) {
	        return '';
	      }

	      return "<span class=\"card-comments\"><i class=\"".concat(className, "\"></i><span>").concat(issue.comments, "</span></span>");
	    }
	  }]);

	  return CardRenderer;
	}(Renderer$1);

	function setColorAlpha(color, alpha) {
	  var reg = /^#([\da-fA-F]{2})([\da-fA-F]{2})([\da-fA-F]{2})$/;
	  var matches = reg.exec(color);
	  var r = parseInt(matches[1], 16);
	  var g = parseInt(matches[2], 16);
	  var b = parseInt(matches[3], 16);
	  return "rgba(".concat(r, ",").concat(g, ",").concat(b, ",").concat(alpha, ")");
	}

	function renderBoardIcon(board) {
	  if (board.icon) {
	    return "<i style=\"color: ".concat(board.color, "\" class=\"").concat(board.icon, "\"></i>");
	  }

	  return '';
	}

	var BoardRenderer =
	/*#__PURE__*/
	function (_Renderer) {
	  _inherits(BoardRenderer, _Renderer);

	  function BoardRenderer() {
	    _classCallCheck(this, BoardRenderer);

	    return _possibleConstructorReturn(this, _getPrototypeOf(BoardRenderer).apply(this, arguments));
	  }

	  _createClass(BoardRenderer, [{
	    key: "render",
	    value: function render(board) {
	      return "<div class=\"board\" data-state=\"".concat(board.state, "\">\n      <div class=\"board-inner\">\n        ").concat(this.renderHeader(board), "\n        <div class=\"board-list-wrapper\">\n          <ul class=\"board-list\"></ul>\n          <div class=\"ui inverted dimmer\">\n            <div class=\"ui loader\"></div>\n          </div>\n          <div class=\"board-blur-message\">\n            <p><i class=\"icon ban\"></i></p>\n            <p>").concat(this.config.message.stateDisabled, "</p>\n          </div>\n        </div>\n    </div>\n    </div>");
	    }
	  }, {
	    key: "renderHeader",
	    value: function renderHeader(board) {
	      var headerStyle = '';
	      var headerClass = 'board-header';

	      if (board.color) {
	        if (board.colorTarget === 'background') {
	          headerStyle = "background-color: ".concat(setColorAlpha(board.color, 0.04));
	        } else {
	          headerClass += ' has-border';
	          headerStyle = "border-color: ".concat(board.color);
	        }
	      }

	      return "<div class=\"".concat(headerClass, "\" style=\"").concat(headerStyle, "\">\n      <h3 class=\"board-title\" style=\"color: ").concat(board.color, "\">\n        ").concat(this.renderActions(), "\n        ").concat(this.renderAvatar(board), "\n        ").concat(renderBoardIcon(board), "\n        <span class=\"board-name\" style=\"color: ").concat(board.color, "\">").concat(htmlSafe(board.name), "</span>\n        <span class=\"issues-count-badge\">\n          <span class=\"issues-count\">").concat(board.issuesCount, "</span>\n        </span>        \n      </h3>\n    </div>");
	    }
	  }, {
	    key: "renderActions",
	    value: function renderActions() {
	      var config = this.config;
	      var actions = config.actions;

	      if (typeof actions === 'function') {
	        actions = actions(config);
	      }

	      return "<div class=\"right floated board-actions ".concat(config.className.actions, "\">\n        ").concat(actions.map(function (a) {
	        return "<button type=\"button\" class=\"board-action ".concat(a["class"], "\"\n            title=\"").concat(a.title, "\" data-id=\"").concat(a.id, "\">\n            <i class=\"").concat(a.icon, "\"></i>\n          </button>");
	      }).join(''), "\n    </div>");
	    }
	  }, {
	    key: "renderAvatar",
	    value: function renderAvatar(board) {
	      if (!board.avatarUrl) {
	        return '';
	      }

	      return "<img class=\"".concat(this.config.className.avatar, " board-avatar\"\n      alt=\"").concat(board.state, "\" src=\"").concat(this.getAvatarUrl(board.name, board.avatarUrl), "\">");
	    }
	  }, {
	    key: "renderTip",
	    value: function renderTip(board) {
	      var msg = this.config.message;

	      if (board.loadable) {
	        return "<li class=\"board-tip\">\n        <span class=\"ui active mini inline loader\"></span>\n        ".concat(msg.loading, "\n      </li>");
	      }

	      if (board.completed && board.issues.length > 0) {
	        return "<li class=\"board-tip\">".concat(msg.allComplete, "</li>");
	      }

	      return "<li class=\"board-tip\">".concat(msg.empty, "</li>");
	    }
	  }]);

	  return BoardRenderer;
	}(Renderer$1);
	var Board =
	/*#__PURE__*/
	function () {
	  function Board(data, config) {
	    var _this = this;

	    _classCallCheck(this, Board);

	    this.page = 0;
	    this.loadable = true;
	    this.loading = false;
	    this.completed = false;
	    this.issues = [];
	    this.name = data.name;
	    this.icon = data.icon;
	    this.state = data.state;
	    this.color = data.color;
	    this.colorTarget = data.colorTarget;
	    this.issuesCount = data.issuesCount || 0;
	    this.avatarUrl = data.avatarUrl;
	    this.config = config;
	    this.renderer = new BoardRenderer(config);
	    this.cardRenderer = new CardRenderer(config);
	    this.$tip = null;
	    this.$el = $(this.renderer.render(this));
	    this.$dimmer = this.$el.find('.ui.dimmer');
	    this.$issues = this.$el.find('.board-list');
	    this.$issuesCount = this.$el.find('.issues-count');
	    this.$issues.on('scroll', function () {
	      _this.autoload();
	    });
	  }

	  _createClass(Board, [{
	    key: "add",
	    value: function add(issue) {
	      this.issues.push(issue);
	      this.issuesCount += 1;
	      this.$issuesCount.text(this.issuesCount);
	    }
	  }, {
	    key: "find",
	    value: function find(id) {
	      for (var i = 0; i < this.issues.length; ++i) {
	        var issue = this.issues[i];

	        if (issue.id === id) {
	          return i;
	        }
	      }

	      return -1;
	    }
	  }, {
	    key: "get",
	    value: function get(id) {
	      var i = this.find(id);

	      if (i >= 0) {
	        return this.issues[i];
	      }

	      return null;
	    }
	  }, {
	    key: "remove",
	    value: function remove(id) {
	      var i = this.find(id);

	      if (i >= 0) {
	        this.issuesCount -= 1;
	        this.$issuesCount.text(this.issuesCount);
	        return this.issues.splice(i, 1);
	      }

	      return null;
	    }
	  }, {
	    key: "clear",
	    value: function clear() {
	      this.page = 0;
	      this.issues = [];
	      this.issuesCount = 0;
	      this.loading = false;
	      this.loadable = true;
	      this.completed = false;
	      this.$issuesCount.text(0);
	      this.$issues.empty();
	      this.$tip = null;
	    }
	  }, {
	    key: "autoload",
	    value: function autoload() {
	      if (this.completed) {
	        return;
	      }

	      if (!this.$tip || this.$tip.position().top < this.$issues.height()) {
	        this.load();
	      }
	    }
	  }, {
	    key: "load",
	    value: function load() {
	      if (this.loading) {
	        return false;
	      }

	      this.page += 1;
	      this.loading = true;

	      if (this.page === 1) {
	        this.$dimmer.addClass('active');
	      }

	      this.config.onLoad(this, this.onLoadDone.bind(this));
	      return true;
	    }
	  }, {
	    key: "onLoadDone",
	    value: function onLoadDone(issues, count) {
	      this.issuesCount = count;
	      this.$issuesCount.text(this.issuesCount);
	      this.appendIssues(issues);

	      if (this.issuesCount > 0) {
	        if (issues.length < 1 || this.issuesCount === issues.length) {
	          this.loadable = false;
	          this.completed = true;
	        } else {
	          this.loadable = true;
	          this.completed = false;
	        }
	      } else {
	        this.loadable = false;
	        this.completed = true;
	      }

	      if (this.page === 1) {
	        this.$dimmer.removeClass('active');
	      }

	      this.loading = false;
	      this.updateTip();
	      this.autoload();
	    }
	    /* 进行初次加载 */

	  }, {
	    key: "firstload",
	    value: function firstload() {
	      if (this.page > 0) {
	        return false;
	      }

	      return this.load();
	    }
	    /**
	     * 更新提示
	    */

	  }, {
	    key: "updateTip",
	    value: function updateTip() {
	      if (this.$tip) {
	        this.$tip.remove();
	      }

	      this.$tip = $(this.renderer.renderTip(this));
	      this.$issues.append(this.$tip);
	    }
	  }, {
	    key: "createCard",
	    value: function createCard(issue) {
	      var $card = $(this.cardRenderer.render(issue));
	      var onSelect = this.config.onSelect;

	      if (onSelect) {
	        $card.on('click', function (e) {
	          var $target = $(e.target);

	          if (!$target.is('a')) {
	            $target = $target.parent();
	          }

	          if (!$target.parent().hasClass('card-header') && $target.is('a') && $target.attr('href')) {
	            return;
	          }

	          onSelect(issue, e);
	        });
	      }

	      return this.config.onRender(issue, $card, this.config);
	    }
	  }, {
	    key: "appendIssue",
	    value: function appendIssue(issue) {
	      this.issues.push(issue);
	      this.$issues.append(this.createCard(issue));
	    }
	  }, {
	    key: "prependIssue",
	    value: function prependIssue(issue) {
	      this.issuesCount += 1;
	      this.issues.splice(0, 0, issue);
	      this.$issues.prepend(this.createCard(issue));
	      this.$issuesCount.text(this.issuesCount);
	    }
	  }, {
	    key: "updateIssue",
	    value: function updateIssue(issue) {
	      var $issue = $("#".concat(this.config.name, "-issue-").concat(issue.id));

	      if ($issue.length < 1) {
	        this.prependIssue(issue);
	        return;
	      }

	      $issue.before(this.createCard(issue)).remove();
	    }
	    /**
	     * 直接追加多个任务，不更新任务总数
	     * @param {Array} issues 任务列表
	     */

	  }, {
	    key: "appendIssues",
	    value: function appendIssues(issues) {
	      var _this2 = this;

	      issues.filter(function (issue) {
	        return _this2.issues.every(function (boardIssue) {
	          return boardIssue.id !== issue.id;
	        });
	      }).forEach(function (issue) {
	        issue[_this2.config.Key] = _this2.state;

	        _this2.appendIssue(issue);
	      });
	    }
	  }]);

	  return Board;
	}();

	var Boards =
	/*#__PURE__*/
	function () {
	  /**
	   * 创建一个看板
	   * @param {JQuery} $el 看板容器元素
	   * @param {BoardsSettings} options 配置
	   */
	  function Boards($el, options) {
	    _classCallCheck(this, Boards);

	    var config = new Config$1(options);
	    this.$el = $el;
	    this.config = config;
	    this.boards = {};
	    this.$hoverIssue = null;
	    this.$selectedIssue = null;
	    this.timerForScrollLoad = null;
	    this.bindDrag();
	    this.bindScroll();
	    this.initPlugins();
	    this.setData(config.data);
	  }

	  _createClass(Boards, [{
	    key: "initPlugins",
	    value: function initPlugins() {
	      this.initSortable();
	    } // 初始化拖拽排序功能

	  }, {
	    key: "initSortable",
	    value: function initSortable() {
	      var that = this;
	      var Sortable = that.config.plugins.Sortable; // 如果没有注入 SortableJS 依赖，则不启用这个功能

	      if (!Sortable) {
	        return false;
	      }

	      that.$el.addClass('boards-sortable');
	      that.sortable = Sortable.create(that.$el[0], {
	        handle: '.board-title',
	        dataIdAttr: 'data-state',
	        onUpdate: function onUpdate() {
	          that.config.onSorted(that.sortable.toArray());
	        }
	      });
	      that.$el.on('click', '.board-action', function (e) {
	        var $target = $(this);
	        var id = $target.data('id');
	        var state = $target.parents('.board').data('state');
	        var actions = that.config.actions;

	        if (typeof actions === 'function') {
	          actions = actions(that.config);
	        }

	        actions.some(function (action) {
	          if (action.id === id && action.callback) {
	            action.callback(that, that.boards[state], e);
	            return true;
	          }

	          return false;
	        });
	      });
	      return true;
	    }
	  }, {
	    key: "bindScroll",
	    value: function bindScroll() {
	      var that = this;
	      var timerForScrollLoad = null;

	      function onScrollLoad() {
	        if (timerForScrollLoad) {
	          clearTimeout(timerForScrollLoad);
	        }

	        timerForScrollLoad = setTimeout(function () {
	          timerForScrollLoad = null;
	          that.load();
	        }, 200);
	      }

	      $(window).on('resize', onScrollLoad);
	      this.$el.on('scroll', onScrollLoad);
	    }
	  }, {
	    key: "bindDrag",
	    value: function bindDrag() {
	      var that = this;

	      if (that.config.readonly) {
	        return;
	      }

	      that.$el.on('dragstart', '.card', function (e) {
	        var issueId = $(this).data('id');
	        var issue = that.getIssue(issueId);

	        if (issue) {
	          that.setFocus(issue.type, issue.state);
	        }

	        that.$selectedIssue = $(this);
	        e.originalEvent.dataTransfer.setData('text/plain', issueId);
	        e.stopPropagation();
	      });
	      that.$el.on('dragend', '.card', function () {
	        that.clearFocus();
	      });
	      that.$el.on('drop', '.board-list', function (e) {
	        e.preventDefault();
	        e.stopPropagation();

	        if (that.$hoverIssue) {
	          that.$hoverIssue.removeClass('card-dragover');
	        }

	        if (!that.$selectedIssue) {
	          return false;
	        }

	        if (that.config.readonly) {
	          return false;
	        }

	        var $issue = that.$selectedIssue;
	        var issueId = $issue.data('id');
	        var $board = $(this).parents('.board');
	        var state = $board.data('state');
	        var oldState = $issue.parents('.board').data('state');
	        var nextIssueId = that.$hoverIssue ? that.$hoverIssue.data('id') : null;
	        that.setIssueState(issueId, state, nextIssueId, function _callee(issue) {
	          return regenerator.async(function _callee$(_context) {
	            while (1) {
	              switch (_context.prev = _context.next) {
	                case 0:
	                  return _context.abrupt("return", that.config.onUpdate(issue, oldState, nextIssueId));

	                case 1:
	                case "end":
	                  return _context.stop();
	              }
	            }
	          });
	        });
	        return true;
	      });
	      that.$el.on('dragover', '.board-list', function (e) {
	        var key = that.config.key;
	        var $target = $(e.target);

	        if (!that.$selectedIssue) {
	          return;
	        }

	        e.preventDefault();

	        while ($target.length > 0 && !$target.hasClass('card')) {
	          $target = $target.parent();
	        }

	        if ($target.length < 1) {
	          if (that.$hoverIssue) {
	            that.$hoverIssue.removeClass('card-dragover');
	          }

	          that.$hoverIssue = null;
	          return;
	        }

	        if (that.$hoverIssue) {
	          that.$hoverIssue.removeClass('card-dragover');
	        }

	        that.$hoverIssue = $target;
	        var hoverIssue = that.getIssue($target.data('id'));
	        var selectedIssue = that.getIssue(that.$selectedIssue.data('id'));

	        if (hoverIssue && selectedIssue && hoverIssue[key] !== selectedIssue[key]) {
	          that.$hoverIssue.addClass('card-dragover');
	        }
	      });
	    }
	    /**
	     * 设置焦点板块
	     * 根据指定的类型和状态，排除无关状态的板块
	     * @param {String, Number} typeId 任务类型 id
	     * @param {String, Number} stateId 任务状态 id
	     */

	  }, {
	    key: "setFocus",
	    value: function setFocus(typeId, stateId) {
	      var _this = this;

	      var stateIds = [];
	      var issueType = null;

	      if (this.config.key !== 'state') {
	        return;
	      }

	      this.config.types.some(function (t) {
	        if (t.id === typeId) {
	          issueType = t;
	          return true;
	        }

	        return false;
	      });

	      if (issueType) {
	        stateIds = issueType.states.map(function (state) {
	          return state.id.toString();
	        });
	      }

	      Object.keys(this.boards).forEach(function (id) {
	        if (id !== stateId.toString() && stateIds.indexOf(id) === -1) {
	          _this.boards[id].$el.addClass('board-blur');
	        }
	      });
	    }
	    /* 清除板块的焦点效果 */

	  }, {
	    key: "clearFocus",
	    value: function clearFocus() {
	      var _this2 = this;

	      Object.keys(this.boards).forEach(function (key) {
	        _this2.boards[key].$el.removeClass('board-blur');
	      });
	    }
	  }, {
	    key: "getIssueCard",
	    value: function getIssueCard(id) {
	      return $("#".concat(this.config.name, "-issue-").concat(id));
	    }
	  }, {
	    key: "getIssue",
	    value: function getIssue(id) {
	      var $issue = this.getIssueCard(id);
	      var $board = $issue.parents('.board');
	      var state = $board.data('state');
	      var board = this.boards[state];

	      if (board) {
	        return board.get(id);
	      }

	      return null;
	    }
	  }, {
	    key: "removeIssue",
	    value: function removeIssue(id) {
	      var issue = null;
	      var $issue = this.getIssueCard(id);

	      if ($issue.length < 1) {
	        return issue;
	      }

	      var state = $issue.parents('.board').data('state');

	      if (state) {
	        var board = this.boards[state];

	        if (board) {
	          issue = board.remove(id);
	        }
	      }

	      $issue.remove();
	      return issue;
	    }
	  }, {
	    key: "updateIssue",
	    value: function updateIssue(issue) {
	      var board = this.boards[issue[this.config.key]];

	      if (board) {
	        board.updateIssue(issue);
	        return true;
	      }

	      return false;
	    }
	  }, {
	    key: "prependIssue",
	    value: function prependIssue(issue) {
	      var board = this.boards[issue[this.config.key]];

	      if (board) {
	        board.prependIssue(issue);
	        return true;
	      }

	      return false;
	    }
	  }, {
	    key: "setIssueState",
	    value: function setIssueState(issueId, state, nextIssueId, callback) {
	      var $issue = this.getIssueCard(issueId);
	      var $nextIssue = nextIssueId ? this.getIssueCard(nextIssueId) : null;

	      if ($issue.length < 1) {
	        return null;
	      }

	      var user = this.config.user;
	      var $oldBoard = $issue.parents('.board');
	      var oldState = $oldBoard.data('state');
	      var oldBoard = this.boards[oldState];
	      var newBoard = this.boards[state];

	      if (oldBoard.state === state) {
	        return null;
	      } // 如果新的板块不接受该状态的 issue


	      if (newBoard.exclude && newBoard.exclude.indexOf(oldState) >= 0) {
	        return null;
	      }

	      var issue = oldBoard.get(issueId); // 如果当前用户既不具备管理权限，也不是 issue 作者，则禁止操作

	      if (!user.admin && issue.author.id !== user.id) {
	        return null;
	      }

	      issue[this.config.key] = state;
	      newBoard.add(issue);
	      oldBoard.remove(issue.id);
	      $issue.hide(256, function () {
	        // 如果有指定下一个 issue，则将当前 issue 插入到它前面
	        if ($nextIssue) {
	          $nextIssue.before($issue);
	        } else {
	          newBoard.$issues.prepend($issue);
	        }

	        $issue.addClass('card-loading');
	        $issue.show(256, function _callee2() {
	          return regenerator.async(function _callee2$(_context2) {
	            while (1) {
	              switch (_context2.prev = _context2.next) {
	                case 0:
	                  if (!callback) {
	                    _context2.next = 3;
	                    break;
	                  }

	                  _context2.next = 3;
	                  return regenerator.awrap(callback(issue));

	                case 3:
	                  $issue.removeClass('card-loading');

	                case 4:
	                case "end":
	                  return _context2.stop();
	              }
	            }
	          });
	        });
	      });
	      newBoard.updateTip();
	      oldBoard.updateTip();
	      oldBoard.autoload();
	      return issue;
	    }
	  }, {
	    key: "load",
	    value: function load() {
	      var _this3 = this;

	      var count = 0;
	      var bound = this.$el.offset(); // 设置边界框（可见区域）的尺寸

	      bound.width = this.$el.width();
	      bound.height = this.$el.height();
	      Object.keys(this.boards).forEach(function (state) {
	        var board = _this3.boards[state];
	        var offset = board.$el.offset(); // 如果当前板块在可见区域内

	        if (offset.top + board.$el.height() > bound.top && offset.left + board.$el.width() > bound.left && offset.top < bound.top + bound.height && offset.left < bound.left + bound.width) {
	          if (board.firstload()) {
	            count += 1;
	          }
	        }
	      });
	      return count;
	    }
	  }, {
	    key: "setData",
	    value: function setData(data) {
	      var _this4 = this;

	      this.boards = {};
	      this.$el.addClass('boards-list').empty();
	      data.forEach(function (boardData) {
	        var board = new Board(boardData, _this4.config);
	        _this4.boards[boardData.state] = board;

	        _this4.$el.append(board.$el);
	      });
	    }
	  }, {
	    key: "clearData",
	    value: function clearData() {
	      var _this5 = this;

	      Object.keys(this.boards).forEach(function (state) {
	        _this5.boards[state].clear();
	      });
	    }
	  }]);

	  return Boards;
	}();

	$.fn.boards = function (options) {
	  var that = this.data('boards');
	  var settings = $.extend({}, $.fn.boards.settings, options);

	  if (!that) {
	    that = new Boards(this, settings);
	    this.data('boards', that);
	    that.load();
	  }

	  return this;
	};

	$.fn.boards.settings = defaults$1;

}());
